From 56f1d4ee8c1974d144a3fa76b2eaf9e69cd09322 Mon Sep 17 00:00:00 2001 From: "postman[bot]" <211381805+postman[bot]@users.noreply.github.com> Date: Tue, 16 Jun 2026 05:00:10 +0000 Subject: [PATCH] SDK Updates: v3.1.0 --- .manifest.json | 676 ++++++--- LICENSE | 2 +- PyPI_README.md | 18 +- README.md | 18 +- documentation/models/AddAnnotationRequest.md | 32 +- .../models/AddEnvelopeSigningStepsRequest.md | 6 +- .../models/AddTemplateSigningStepsRequest.md | 6 +- documentation/models/Annotation.md | 34 +- documentation/models/AnnotationCheckbox.md | 8 +- documentation/models/AnnotationDateTime.md | 18 +- documentation/models/AnnotationFont.md | 10 +- documentation/models/AnnotationText.md | 16 +- documentation/models/AttachmentPlaceholder.md | 18 +- .../AttachmentPlaceholdersPerRecipient.md | 10 +- documentation/models/CreateEnvelopeRequest.md | 14 +- documentation/models/CreateWebhookRequest.md | 8 +- documentation/models/Document.md | 14 +- documentation/models/Envelope.md | 36 +- documentation/models/EnvelopeAttachments.md | 8 +- ...ListEnvelopeDocumentAnnotationsResponse.md | 6 +- .../models/ListEnvelopeDocumentsResponse.md | 6 +- documentation/models/ListEnvelopesRequest.md | 38 +- documentation/models/ListEnvelopesResponse.md | 10 +- .../models/ListTemplateAnnotationsResponse.md | 6 +- ...ListTemplateDocumentAnnotationsResponse.md | 6 +- .../models/ListTemplateDocumentsResponse.md | 6 +- documentation/models/ListTemplatesRequest.md | 22 +- documentation/models/ListTemplatesResponse.md | 10 +- documentation/models/ListWebhooksRequest.md | 8 +- documentation/models/ListWebhooksResponse.md | 6 +- documentation/models/Recipient.md | 16 +- documentation/models/RecipientVerification.md | 8 +- ...tEnvelopeAttachmentsPlaceholdersRequest.md | 6 +- .../SetEnvelopeAttachmentsSettingsRequest.md | 6 +- .../models/SetEnvelopeDynamicFieldsRequest.md | 6 +- .../models/SetEnvelopeLegalityLevelRequest.md | 6 +- documentation/models/SigningStep.md | 6 +- documentation/models/Template.md | 32 +- documentation/models/TemplateRecipient.md | 14 +- documentation/models/TemplateSigningStep.md | 6 +- documentation/models/Webhook.md | 10 +- documentation/services/SignplusService.md | 70 +- documentation/snippets/snippets.json | 282 ++++ examples/install.cmd | 2 +- examples/install.sh | 19 +- install.cmd | 2 +- install.sh | 17 +- prettier.config.js | 41 + pyproject.toml | 13 +- src/signplus/models/__init__.py | 271 +++- src/signplus/models/add_annotation_request.py | 116 +- .../models/add_envelope_document_request.py | 17 +- .../add_envelope_signing_steps_request.py | 17 +- .../models/add_template_document_request.py | 13 +- .../add_template_signing_steps_request.py | 15 +- src/signplus/models/annotation.py | 145 +- src/signplus/models/annotation_checkbox.py | 31 +- .../models/annotation_checkbox_style.py | 7 +- src/signplus/models/annotation_date_time.py | 68 +- .../models/annotation_date_time_format.py | 7 +- src/signplus/models/annotation_font.py | 37 +- src/signplus/models/annotation_font_family.py | 7 +- src/signplus/models/annotation_initials.py | 20 +- src/signplus/models/annotation_signature.py | 20 +- src/signplus/models/annotation_text.py | 59 +- src/signplus/models/annotation_type.py | 7 +- src/signplus/models/attachment_placeholder.py | 69 +- .../models/attachment_placeholder_file.py | 39 +- .../models/attachment_placeholder_request.py | 52 +- .../attachment_placeholders_per_recipient.py | 33 +- src/signplus/models/attachment_settings.py | 17 +- .../create_envelope_from_template_request.py | 39 +- .../models/create_envelope_request.py | 60 +- .../models/create_template_request.py | 21 +- src/signplus/models/create_webhook_request.py | 17 +- src/signplus/models/document.py | 54 +- src/signplus/models/dynamic_field.py | 20 +- src/signplus/models/envelope.py | 138 +- src/signplus/models/envelope_attachments.py | 27 +- src/signplus/models/envelope_flow_type.py | 7 +- .../models/envelope_legality_level.py | 7 +- src/signplus/models/envelope_notification.py | 37 +- src/signplus/models/envelope_order_field.py | 7 +- src/signplus/models/envelope_status.py | 7 +- ..._envelope_document_annotations_response.py | 15 +- .../list_envelope_documents_response.py | 15 +- src/signplus/models/list_envelopes_request.py | 135 +- .../models/list_envelopes_response.py | 35 +- .../list_template_annotations_response.py | 15 +- ..._template_document_annotations_response.py | 15 +- .../list_template_documents_response.py | 15 +- src/signplus/models/list_templates_request.py | 73 +- .../models/list_templates_response.py | 35 +- src/signplus/models/list_webhooks_request.py | 24 +- src/signplus/models/list_webhooks_response.py | 15 +- src/signplus/models/page.py | 24 +- src/signplus/models/recipient.py | 56 +- src/signplus/models/recipient_role.py | 7 +- src/signplus/models/recipient_verification.py | 37 +- .../models/recipient_verification_type.py | 7 +- .../models/rename_envelope_request.py | 15 +- .../models/rename_template_request.py | 13 +- ...velope_attachments_placeholders_request.py | 15 +- ...t_envelope_attachments_settings_request.py | 13 +- .../models/set_envelope_comment_request.py | 13 +- .../set_envelope_dynamic_fields_request.py | 13 +- .../models/set_envelope_expiration_request.py | 13 +- .../set_envelope_legality_level_request.py | 20 +- .../models/set_template_comment_request.py | 13 +- src/signplus/models/signing_step.py | 17 +- src/signplus/models/template.py | 120 +- src/signplus/models/template_order_field.py | 7 +- src/signplus/models/template_recipient.py | 54 +- .../models/template_recipient_role.py | 7 +- src/signplus/models/template_signing_step.py | 17 +- src/signplus/models/utils/base_error.py | 116 ++ src/signplus/models/utils/base_model.py | 378 ++--- src/signplus/models/utils/cast_models.py | 44 +- .../models/utils/one_of_base_model.py | 12 + src/signplus/models/webhook.py | 38 +- src/signplus/models/webhook_event.py | 7 +- src/signplus/net/headers/base_header.py | 17 + .../request_chain/handlers/http_handler.py | 50 +- .../request_chain/handlers/retry_handler.py | 105 +- src/signplus/net/sdk_config.py | 63 + src/signplus/net/transport/api_error.py | 12 +- src/signplus/net/transport/request.py | 18 +- src/signplus/net/transport/response.py | 32 +- src/signplus/net/transport/serializer.py | 25 +- src/signplus/net/transport/utils.py | 12 +- src/signplus/sdk.py | 12 +- src/signplus/services/async_/signplus.py | 431 ++++-- src/signplus/services/signplus.py | 1320 ++++++++++++++--- src/signplus/services/utils/base_service.py | 91 +- 134 files changed, 4118 insertions(+), 2684 deletions(-) create mode 100644 documentation/snippets/snippets.json create mode 100644 prettier.config.js create mode 100644 src/signplus/models/utils/base_error.py create mode 100644 src/signplus/net/sdk_config.py diff --git a/.manifest.json b/.manifest.json index 3eda50e..0ff03f9 100644 --- a/.manifest.json +++ b/.manifest.json @@ -1,24 +1,28 @@ { - "liblabVersion": "2.25.46", - "date": "2025-09-17T12:01:31.599Z", + "sdkGenVersion": "1.5.0", + "date": "2026-06-16T05:00:02.613Z", "config": { - "apiId": 2744, - "sdkName": "signplus", - "sdkVersion": "1.4.0", - "languages": ["python"], - "auth": ["bearer"], - "docs": [], - "liblabVersion": "2", - "deliveryMethods": ["zip"], - "rawConfig": { - "sdkName": "signplus", - "apiVersion": "2.5.0", - "apiName": "signplus-api", - "specFilePath": "openapi.yaml", - "languages": ["csharp", "go", "python", "typescript", "java", "php"], - "auth": ["bearer"], - "customizations": { - "includeOptionalSnippetParameters": true, + "sdkVersion": "3.1.0", + "auth": [ + "bearer" + ], + "apiVersion": "2.5.0", + "publishing": { + "githubOrg": "alohihq", + "enabled": false, + "releaseBranch": "main" + }, + "languageOptions": { + "java": { + "githubRepoName": "signplus-java", + "retry": { + "enabled": true, + "maxAttempts": 3, + "retryDelay": 150 + }, + "license": { + "type": "MIT" + }, "authentication": { "access": { "prefix": "Bearer" @@ -26,169 +30,255 @@ }, "devContainer": false, "generateEnv": true, + "responseHeaders": false, + "includeOptionalSnippetParameters": true, + "injectedModels": [], "inferServiceNames": false, + "groupId": "com.alohi", + "artifactId": "signplus", + "developers": [ + { + "name": "Alohi SA", + "email": "support@alohi.com", + "organization": "Alohi SA", + "organizationUrl": "https://www.alohi.com" + } + ] + }, + "typescript": { + "githubRepoName": "signplus-typescript", + "retry": { + "enabled": true, + "maxAttempts": 3, + "retryDelay": 150 + }, + "license": { + "type": "MIT" + }, + "authentication": { + "access": { + "prefix": "Bearer" + } + }, + "devContainer": false, + "generateEnv": true, + "responseHeaders": false, + "includeOptionalSnippetParameters": true, "injectedModels": [], + "inferServiceNames": false, + "npmOrg": "alohi", + "npmName": "signplus-typescript", + "httpClient": "axios", + "bundle": false, + "exportClassDefault": false + }, + "python": { + "githubRepoName": "signplus-python", + "retry": { + "enabled": true, + "maxAttempts": 3, + "retryDelay": 150 + }, "license": { "type": "MIT" }, + "authentication": { + "access": { + "prefix": "Bearer" + } + }, + "devContainer": false, + "generateEnv": true, "responseHeaders": false, + "includeOptionalSnippetParameters": true, + "injectedModels": [], + "inferServiceNames": false, + "pypiPackageName": "signplus-python", + "classifiers": [ + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: MIT License", + "Topic :: Software Development" + ] + }, + "kotlin": { "retry": { "enabled": true, "maxAttempts": 3, "retryDelay": 150 - } + }, + "license": { + "type": "MIT" + }, + "authentication": { + "access": { + "prefix": "Bearer" + } + }, + "devContainer": false, + "generateEnv": true, + "responseHeaders": false, + "includeOptionalSnippetParameters": true, + "injectedModels": [], + "inferServiceNames": false }, - "languageOptions": { - "python": { - "alwaysInitializeOptionals": false, - "pypiPackageName": "signplus-python", - "githubRepoName": "signplus-python", - "ignoreFiles": [], - "sdkVersion": "1.4.0", - "liblabVersion": "2", - "additionalConstructorParameters": [] + "ruby": { + "retry": { + "enabled": true, + "maxAttempts": 3, + "retryDelay": 150 }, - "java": { - "githubRepoName": "signplus-java", - "groupId": "com.alohi", - "artifactId": "signplus", - "sdkVersion": "2.4.0", - "liblabVersion": "2", - "developers": [ - { - "name": "Alohi SA", - "email": "support@alohi.com", - "organization": "Alohi SA", - "organizationUrl": "https://www.alohi.com" - } - ], - "additionalConstructorParameters": [] + "license": { + "type": "MIT" }, - "typescript": { - "bundle": false, - "exportClassDefault": false, - "httpClient": "axios", - "npmName": "signplus-typescript", - "npmOrg": "alohi", - "githubRepoName": "signplus-typescript", - "ignoreFiles": [], - "sdkVersion": "2.4.0", - "liblabVersion": "2", - "additionalConstructorParameters": [] + "authentication": { + "access": { + "prefix": "Bearer" + } }, - "go": { - "goModuleName": "github.com/alohihq/signplus-go", - "githubRepoName": "signplus-go", - "ignoreFiles": [], - "sdkVersion": "1.4.0", - "liblabVersion": "2", - "additionalConstructorParameters": [] + "devContainer": false, + "generateEnv": true, + "responseHeaders": false, + "includeOptionalSnippetParameters": true, + "injectedModels": [], + "inferServiceNames": false + }, + "go": { + "githubRepoName": "signplus-sharp", + "retry": { + "enabled": true, + "maxAttempts": 3, + "retryDelay": 150 }, - "php": { - "packageName": "alohi/signplus", - "githubRepoName": "signplus-php", - "ignoreFiles": [], - "sdkVersion": "2.4.0", - "liblabVersion": "2", - "additionalConstructorParameters": [] + "license": { + "type": "MIT" }, - "csharp": { - "packageId": "Alohi.Signplus", - "githubRepoName": "signplus-sharp", - "ignoreFiles": [], - "sdkVersion": "1.4.0", - "liblabVersion": "2" - } + "authentication": { + "access": { + "prefix": "Bearer" + } + }, + "devContainer": false, + "generateEnv": true, + "responseHeaders": false, + "includeOptionalSnippetParameters": true, + "injectedModels": [], + "inferServiceNames": false, + "goModuleName": "github.com/alohihq/signplus-go" }, - "publishing": { - "githubOrg": "alohihq" - } - }, - "liblabConfigVersion": "1.0.0", - "apiVersion": "2.5.0", - "apiName": "signplus-api", - "specFilePath": "openapi.yaml", - "createDocs": false, - "languageOptions": { "csharp": { "githubRepoName": "signplus-sharp", - "ignoreFiles": [], - "liblabVersion": "2", - "renameIllegalModelProperties": true, - "sdkVersion": "1.4.0", - "packageId": "Alohi.Signplus" - }, - "go": { - "githubRepoName": "signplus-go", - "ignoreFiles": [], - "liblabVersion": "2", - "renameIllegalModelProperties": true, - "sdkVersion": "1.4.0", - "goModuleName": "github.com/alohihq/signplus-go", - "additionalConstructorParameters": [] - }, - "java": { - "githubRepoName": "signplus-java", - "ignoreFiles": [], - "liblabVersion": "2", - "renameIllegalModelProperties": true, - "sdkVersion": "2.4.0", - "groupId": "com.alohi", - "artifactId": "signplus", - "includeKotlinSnippets": false, - "developers": [ - { - "name": "Alohi SA", - "email": "support@alohi.com", - "organization": "Alohi SA", - "organizationUrl": "https://www.alohi.com" + "retry": { + "enabled": true, + "maxAttempts": 3, + "retryDelay": 150 + }, + "license": { + "type": "MIT" + }, + "authentication": { + "access": { + "prefix": "Bearer" } - ], - "additionalConstructorParameters": [] - }, - "python": { - "githubRepoName": "signplus-python", - "ignoreFiles": [], - "liblabVersion": "2", - "renameIllegalModelProperties": true, - "sdkVersion": "1.4.0", - "alwaysInitializeOptionals": false, - "additionalConstructorParameters": [], - "pypiPackageName": "signplus-python" + }, + "devContainer": false, + "generateEnv": true, + "responseHeaders": false, + "includeOptionalSnippetParameters": true, + "injectedModels": [], + "inferServiceNames": false, + "packageId": "Alohi.Signplus" }, "php": { "githubRepoName": "signplus-php", - "ignoreFiles": [], - "liblabVersion": "2", - "renameIllegalModelProperties": true, - "sdkVersion": "2.4.0", - "additionalConstructorParameters": [], + "retry": { + "enabled": true, + "maxAttempts": 3, + "retryDelay": 150 + }, + "license": { + "type": "MIT" + }, + "authentication": { + "access": { + "prefix": "Bearer" + } + }, + "devContainer": false, + "generateEnv": true, + "responseHeaders": false, + "includeOptionalSnippetParameters": true, + "injectedModels": [], + "inferServiceNames": false, "packageName": "alohi/signplus" }, - "typescript": { - "githubRepoName": "signplus-typescript", - "ignoreFiles": [], - "liblabVersion": "2", - "renameIllegalModelProperties": true, - "sdkVersion": "2.4.0", - "additionalConstructorParameters": [], - "bundle": false, - "denoteCommon": false, - "exportClassDefault": false, - "generateEnumAs": "enum", - "httpClient": "axios", - "npmName": "signplus-typescript", - "npmOrg": "alohi" + "cli": { + "retry": { + "enabled": true, + "maxAttempts": 3, + "retryDelay": 150 + }, + "license": { + "type": "MIT" + }, + "authentication": { + "access": { + "prefix": "Bearer" + } + }, + "devContainer": false, + "generateEnv": true, + "responseHeaders": false, + "includeOptionalSnippetParameters": true, + "injectedModels": [], + "inferServiceNames": false + }, + "rust": { + "retry": { + "enabled": true, + "maxAttempts": 3, + "retryDelay": 150 + }, + "license": { + "type": "MIT" + }, + "authentication": { + "access": { + "prefix": "Bearer" + } + }, + "devContainer": false, + "generateEnv": true, + "responseHeaders": false, + "includeOptionalSnippetParameters": true, + "injectedModels": [], + "inferServiceNames": false } }, - "validationsToIgnore": [], - "publishing": { - "githubOrg": "alohihq", - "platform": "github" + "customCode": { + "trackChanges": true + }, + "retry": { + "enabled": true, + "maxAttempts": 3, + "retryDelay": 150, + "maxDelay": 5000, + "retryDelayJitter": 50, + "backOffFactor": 2, + "httpMethodsToRetry": [ + "GET", + "POST", + "PUT", + "DELETE", + "PATCH", + "HEAD", + "OPTIONS" + ] }, - "analytics": { - "streaming": false, - "pagination": false + "license": { + "type": "MIT", + "name": "MIT", + "url": "https://opensource.org/licenses/MIT", + "path": "MIT.ejs" }, "authentication": { "access": { @@ -197,33 +287,24 @@ }, "devContainer": false, "generateEnv": true, - "includeOptionalSnippetParameters": true, - "license": { - "type": "MIT", - "name": "MIT", - "url": "https://opensource.org/licenses/MIT", - "path": "MIT.ejs" - }, "responseHeaders": false, - "buildAllModels": false, - "retry": { - "enabled": true, - "maxAttempts": 3, - "retryDelay": 150, - "maxDelay": 5000, - "retryDelayJitter": 50, - "backOffFactor": 2, - "httpCodesToRetry": [408, 429, 500, 502, 503, 504], - "httpMethodsToRetry": ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"] - }, - "multiTenant": true, - "includeWatermark": false, + "includeOptionalSnippetParameters": true, + "injectedModels": [], + "inferServiceNames": false, + "languages": [ + "python" + ], + "deliveryMethods": [ + "zip" + ], + "sdkName": "signplus", "githubRepoName": "signplus-python", - "ignoreFiles": [], - "renameIllegalModelProperties": true, - "alwaysInitializeOptionals": false, - "additionalConstructorParameters": [], "pypiPackageName": "signplus-python", + "classifiers": [ + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: MIT License", + "Topic :: Software Development" + ], "language": "python", "deliveryMethod": "zip", "hooks": { @@ -233,14 +314,14 @@ "usesFormData": false, "environmentVariables": [], "fileOutput": "/tmp", - "inferServiceNames": false, "httpLibrary": { "name": "axios", - "packages": { - "axios": "^1.9.0" - }, - "languages": ["typescript"] + "packages": {}, + "languages": [ + "typescript" + ] }, + "multiTenant": false, "customQueries": { "paths": [], "rawQueries": [], @@ -250,10 +331,14 @@ "specType": "openapi", "deprecatedOperations": { "include": true + }, + "multipleResponses": { + "enabled": false } }, "files": [ "src/signplus/models/utils/base_model.py", + "src/signplus/models/utils/base_error.py", "src/signplus/models/utils/json_map.py", "src/signplus/models/__init__.py", "src/signplus/services/__init__.py", @@ -262,7 +347,6 @@ "src/signplus/net/__init__.py", "src/signplus/net/headers/__init__.py", "src/signplus/net/transport/__init__.py", - "src/signplus/hooks/__init__.py", "src/signplus/net/environment/__init__.py", "src/signplus/net/request_chain/__init__.py", "src/signplus/net/request_chain/handlers/__init__.py", @@ -281,7 +365,6 @@ ".gitignore", "src/signplus/models/utils/cast_models.py", "src/signplus/net/transport/utils.py", - "src/signplus/hooks/hook.py", "install.sh", "install.cmd", "examples/install.sh", @@ -292,11 +375,11 @@ "src/signplus/net/request_chain/request_chain.py", "src/signplus/net/request_chain/handlers/base_handler.py", "src/signplus/net/request_chain/handlers/http_handler.py", - "src/signplus/net/request_chain/handlers/hook_handler.py", "src/signplus/net/request_chain/handlers/retry_handler.py", "examples/sample.py", "src/signplus/services/utils/default_headers.py", "LICENSE", + "documentation/snippets/snippets.json", "documentation/models/CreateEnvelopeRequest.md", "documentation/models/Envelope.md", "documentation/models/CreateEnvelopeFromTemplateRequest.md", @@ -371,19 +454,7 @@ "src/signplus/models/utils/sentinel.py", ".env.example", "examples/.env.example", - "src/signplus/models/envelope_legality_level.py", - "src/signplus/models/envelope_flow_type.py", - "src/signplus/models/envelope_status.py", - "src/signplus/models/recipient_role.py", - "src/signplus/models/recipient_verification_type.py", - "src/signplus/models/envelope_order_field.py", - "src/signplus/models/annotation_type.py", - "src/signplus/models/annotation_font_family.py", - "src/signplus/models/annotation_date_time_format.py", - "src/signplus/models/annotation_checkbox_style.py", - "src/signplus/models/template_recipient_role.py", - "src/signplus/models/template_order_field.py", - "src/signplus/models/webhook_event.py", + "src/signplus/net/sdk_config.py", "src/signplus/models/create_envelope_request.py", "src/signplus/models/envelope.py", "src/signplus/models/create_envelope_from_template_request.py", @@ -420,27 +491,232 @@ "src/signplus/models/webhook.py", "src/signplus/models/list_webhooks_request.py", "src/signplus/models/list_webhooks_response.py", + "src/signplus/models/envelope_legality_level.py", + "src/signplus/models/envelope_flow_type.py", + "src/signplus/models/envelope_status.py", "src/signplus/models/signing_step.py", "src/signplus/models/recipient.py", + "src/signplus/models/recipient_role.py", "src/signplus/models/recipient_verification.py", + "src/signplus/models/recipient_verification_type.py", "src/signplus/models/page.py", "src/signplus/models/attachment_settings.py", "src/signplus/models/attachment_placeholders_per_recipient.py", "src/signplus/models/attachment_placeholder.py", "src/signplus/models/attachment_placeholder_file.py", + "src/signplus/models/envelope_order_field.py", "src/signplus/models/dynamic_field.py", "src/signplus/models/attachment_placeholder_request.py", + "src/signplus/models/annotation_type.py", "src/signplus/models/annotation_signature.py", "src/signplus/models/annotation_initials.py", "src/signplus/models/annotation_text.py", "src/signplus/models/annotation_date_time.py", "src/signplus/models/annotation_checkbox.py", "src/signplus/models/annotation_font.py", + "src/signplus/models/annotation_font_family.py", + "src/signplus/models/annotation_date_time_format.py", + "src/signplus/models/annotation_checkbox_style.py", "src/signplus/models/template_signing_step.py", "src/signplus/models/template_recipient.py", + "src/signplus/models/template_recipient_role.py", + "src/signplus/models/template_order_field.py", + "src/signplus/models/webhook_event.py", "README.md", "PyPI_README.md", "documentation/services/SignplusService.md", "src/signplus/services/signplus.py" - ] + ], + "fileHashes": { + ".env.example": "4fb1ccb01931cc8124c1fd6d88721547b83f2d48bd0ddf29b4827a31983ad12c", + ".gitignore": "6bbf1931dedfa978c086f704675227391491eeb602840bea6d83e20394768b77", + "LICENSE": "3ec558dc6e9c9355ab4b28c942caa92bf90b0b82c12d7838d2ef92467ad135c1", + "PyPI_README.md": "53baf8513cd08763c8a44329acd8384160beb35d8236d8235a64cc2918398862", + "README.md": "b10712f7f8475e3435e1f5805552df11a558b747cca1381d02bca0d7ecec357c", + "documentation/models/AddAnnotationRequest.md": "2817c038118d15fab503e4e1467c9c6ed18026d3fd5afe391a627c6fa84652d0", + "documentation/models/AddEnvelopeDocumentRequest.md": "f893dc1b08ad39935a449443485043d1f1eaa8536353b1b0e5facd2ace71dc1f", + "documentation/models/AddEnvelopeSigningStepsRequest.md": "3a1b9130ef80b069204aa1e053dc3383754944ba6b9ee8dadd4774aa9bf71f88", + "documentation/models/AddTemplateDocumentRequest.md": "522f4c3cc215071b13ed4974a203ff6cf347ae3e0eb6b489c6d6dc79be3c5455", + "documentation/models/AddTemplateSigningStepsRequest.md": "3e72530ab4ce4cebd69bc63bb3d8de71dcffddcfb5c7362e29c9c4b43db9b72d", + "documentation/models/Annotation.md": "5198c2349fbb05ed6634bdb0a9ad4595869220311d807faf753f840dcd9d444d", + "documentation/models/AnnotationCheckbox.md": "1523e92ac89d43dbb71937a42353c45d06c8ff3f69e246b42aaa3e367bab8698", + "documentation/models/AnnotationCheckboxStyle.md": "d76b76c887822c0e0b5fcb1e3637e0240400e0050bb5003eb650163d38b095dd", + "documentation/models/AnnotationDateTime.md": "961c811556f138a7243616b2769a040def5fb367e6a92b21131d1f4e4572e2bc", + "documentation/models/AnnotationDateTimeFormat.md": "65d59d71b155a3fdf813e714d19f0c1c5ada4575baad57b6b6fc422f9e99e967", + "documentation/models/AnnotationFont.md": "d5f44b084293db11f731089d269e4ba36c128df71e1111d25ee12f430f61a974", + "documentation/models/AnnotationFontFamily.md": "e0ef7319e76b42e0820214dbebd1f57d7836e7f3870b891f4ecb92c91be29e0e", + "documentation/models/AnnotationInitials.md": "e52c1b7b1306a3d436c5d0f0936eea74aed703058719962e95e6b3469b1d37fc", + "documentation/models/AnnotationSignature.md": "ef57a0fa403de8a016aa5c7b33c5e638023875c1371f89b554142c985f727a95", + "documentation/models/AnnotationText.md": "6ac9fe2c77744510cb9da323dbb6bdb9465e78260a7b757605c3840e7d38fdb8", + "documentation/models/AnnotationType.md": "3b566c30379ca0ba1914ebfe1a4621d91eddcdccd2ef78814610617089f4515f", + "documentation/models/AttachmentPlaceholder.md": "6658004593d57bc11a9723a0065eda2e5f0f69aa651ea131cf8d1924141ec58c", + "documentation/models/AttachmentPlaceholderFile.md": "f796f50d472f698a5b64563a75a64b1ab9b9b1263dfa9d701a93ad5f361b6b2b", + "documentation/models/AttachmentPlaceholderRequest.md": "1ce63da28c0fc4c4ce30f9001945525abc2d340622126ae8a6cbee7098cb66c4", + "documentation/models/AttachmentPlaceholdersPerRecipient.md": "edc00c19c0c36cb8a125eacd9848d127181dffa1e8bba2d70d8148d1f0988763", + "documentation/models/AttachmentSettings.md": "7619cbae5dd5a4edda120ffebbd139faf3ffef75aaa90f9b6ff5033dcc7bd6be", + "documentation/models/CreateEnvelopeFromTemplateRequest.md": "5ba6ee826e5195aba1b0f8ec21ca50387720179c26745600352c5ad0c6f6b220", + "documentation/models/CreateEnvelopeRequest.md": "757c6a80f16b227a9c0c2fa41f2bfcbd6f78f31d8b8312d4b43445e5ac791a92", + "documentation/models/CreateTemplateRequest.md": "8dbad09c6bab7b99d23070f96d2af22cfa1f773724ad199840e06c3d1f1121a4", + "documentation/models/CreateWebhookRequest.md": "115fa0ab6b20df29ed80c5396e3509c6a33780aadde1f9f332d0b30701283c5f", + "documentation/models/Document.md": "82d339856865d0d515ac7e725f49bcc2b532b65be73d76b9a2af335b7405e085", + "documentation/models/DynamicField.md": "5b8d673c9d99df1001abfdad4bc7730e6a9f23babacac42fff03bfe0fcc4584a", + "documentation/models/Envelope.md": "06c88dc2ddac54bf79b381b88f2bdef2dedc31466e5964755774b904afc2c563", + "documentation/models/EnvelopeAttachments.md": "c3ab34b21e33dfbe3100399e55b4c0eaaf381e4f3dad7f0631f6f4128112eea6", + "documentation/models/EnvelopeFlowType.md": "512665810bbd4ea6896b934f31baf0a481c105cde5d9a0f7bc132d7cdd4f1ee5", + "documentation/models/EnvelopeLegalityLevel.md": "1dc126869204f2a86312cddab1ccbd3ea991db220403405376da95c4f3a278b3", + "documentation/models/EnvelopeNotification.md": "cce533ec5fe62b3d257a7412f1feb2b2da0479805aef66b4329fbfe6cb069a6b", + "documentation/models/EnvelopeOrderField.md": "fd97db0c36720a083026d0ae558cc143161ea9dba64ffbbb4576ec1fd575ecac", + "documentation/models/EnvelopeStatus.md": "550ca1b1460a33714c23c2d39389fdb23b349ec417d333fba3040ac196d91153", + "documentation/models/ListEnvelopeDocumentAnnotationsResponse.md": "266273c9186a2d1011573f970248c4ae20c35f7318486db226a159b2d6df571c", + "documentation/models/ListEnvelopeDocumentsResponse.md": "72745eedda76bc2ad4ef9dbe218fa9d56aa5281513bcf26406a8b5eab13625c6", + "documentation/models/ListEnvelopesRequest.md": "e2ef9871188c746bca5c290c06da207815b6151617f454c89fb3d0275ebf2942", + "documentation/models/ListEnvelopesResponse.md": "453ce930763f6bcd0d62342aa452f2b04a2c2ba28335574bc4515a1867d70504", + "documentation/models/ListTemplateAnnotationsResponse.md": "fb0414e35c4326ca670ecef534a09a7ec0c62494cb4c7bda189a74ce97427dc5", + "documentation/models/ListTemplateDocumentAnnotationsResponse.md": "bbede728f1e7452b15d053bb2b211910e654a14f0a11dbd722f2959fd86187cc", + "documentation/models/ListTemplateDocumentsResponse.md": "074c87e4e04cdeade4636b4265da6857108b50b6241959a72ebd2b601959e9c0", + "documentation/models/ListTemplatesRequest.md": "51cb320d5078a0adec7ee66f0ab87e2b6c4eeb483a1807069b961a7491853dac", + "documentation/models/ListTemplatesResponse.md": "79aa06ef809a1769c6b534b31b6f426fe70602bdfdbe7c3c333607580ae3e251", + "documentation/models/ListWebhooksRequest.md": "8c858ef2c367885126c564c77e8f594bec396f0a5f90dc25e74407d9d41d6251", + "documentation/models/ListWebhooksResponse.md": "76d598d17fc111d8a42b18e091f2982700cada1625e805d7f32db5be38849801", + "documentation/models/Page.md": "e327eb887b99a62c897219e5f284b5298bbe0f92a90ee15ed11abb2a2196ae1b", + "documentation/models/Recipient.md": "c156bfe9ea98292a3000d10324d07c70cd06d785f42494434a68778e7e415801", + "documentation/models/RecipientRole.md": "c9c4972ab6577d63e4689b60811c0d33ccb75af83d05aab7d32e749e8e264b2e", + "documentation/models/RecipientVerification.md": "5f3f7557488f81361fd0eb2a80ab71f10c3daa6c2d066c07e6c3e43041f435ed", + "documentation/models/RecipientVerificationType.md": "b35280eb5c30498853086b40e02d2723c6b99871d502e371bf5f59e14e67b717", + "documentation/models/RenameEnvelopeRequest.md": "7f43aa2bac58e39f799b643b2685f15ec6506bb953e08df89e320e0d533771a7", + "documentation/models/RenameTemplateRequest.md": "f87a2fc4732b2340038ce8cc7e76a83cbf22b50d0f9991a5a618d3bd50748e9f", + "documentation/models/SetEnvelopeAttachmentsPlaceholdersRequest.md": "3b913fb62763e63fe6b008ba95d30e3240b96d1d985f5eae599313489c387206", + "documentation/models/SetEnvelopeAttachmentsSettingsRequest.md": "fd716156384b28055ce14bb303fc1b9e1811985d9ae13a8ddb0aec44059920e6", + "documentation/models/SetEnvelopeCommentRequest.md": "da9191cbd929c2b37f19d763f2953a73c3133c0d49459b34e50744a44b9f4c15", + "documentation/models/SetEnvelopeDynamicFieldsRequest.md": "885af2a3414460fc0fd67726fc695d1dfd1d41ea78341b23e8247e4bdf38b3ff", + "documentation/models/SetEnvelopeExpirationRequest.md": "5bc1e8b7a79166903ebd3288e45720d05449cf49c289c41f540ba6c811ede8e0", + "documentation/models/SetEnvelopeLegalityLevelRequest.md": "3ce3dcb32cbd60071d7c2c0152716abc19f3cccdd9ba8467e868b563072012bd", + "documentation/models/SetTemplateCommentRequest.md": "1e523e39f2ccbec69a10b0cc38f712a1ade69d271d2ac896e407fb8d20ba5d93", + "documentation/models/SigningStep.md": "0d9de3a9a283c06b0e25b54250c0f5fc199d5837c976b67daaed1e978b771ad2", + "documentation/models/Template.md": "5350593c7c64c71b0576148c6a60bf03989f61c64c19c5c5052e3a3207f59d93", + "documentation/models/TemplateOrderField.md": "3333426bae8b580f89e409b98ea64cfd128028de9d59b58c35286bb097f2be42", + "documentation/models/TemplateRecipient.md": "2c73908653aaabf7554a7a656496db8784d140c82e7839b8a049173c2a1a2c30", + "documentation/models/TemplateRecipientRole.md": "034fabed7d210836585561e8d49f135e4ddf82c60faf00a5066c6665f9ed9a62", + "documentation/models/TemplateSigningStep.md": "559c098fb21fbf58def6243315235fe0ea065833c918a80945cda6737319c365", + "documentation/models/Webhook.md": "4a5daa2901dc730c9fb949642f42a8e17f373a0d94cc54e9080fc23badda4d6b", + "documentation/models/WebhookEvent.md": "1806a70b3ac5c6725b4d8f98b6f0328007ef8769a829a16e2b8d4141c24e724b", + "documentation/services/SignplusService.md": "6dcdadee6c6d703bf462fc2d601806a23afea70f15de8a39ce3eb70741ba0572", + "documentation/snippets/snippets.json": "f69e591a5f451eff01c6d8325d98124c8d8b7c2efc23b68be9a02968e00beea4", + "examples/.env.example": "4fb1ccb01931cc8124c1fd6d88721547b83f2d48bd0ddf29b4827a31983ad12c", + "examples/install.cmd": "0a736e43ca04071808d2293dcaba0336fff1fe887c60300a4ce54df9e167070e", + "examples/install.sh": "2fb1c4beca1ad9489b64f9e7fdcac8c95cc247ce8246732a84f94fdbb0d8c2a2", + "examples/sample.py": "7d37e2bcf73987d25707b971cbdb352819f2fa1a9577de75e3f0a58c386a3cd0", + "install.cmd": "98cf015a8fe2765e8c943f49e3c8d6104b79b5fec0419ebb710cf6c30333668e", + "install.sh": "b2dee52c30f3a18a684ccda664a3c33d2af8edfe80ba253c6031484f4fe4cd3f", + "prettier.config.js": "2fe33fda52344779fcf235afa8152cfd356880dc3161da09403dc26231bc72d9", + "pyproject.toml": "bb9fc30452c3a673edffeca9af3594bc247a2cdc1d6e1ccc7e3f261ba03d34c4", + "src/signplus/__init__.py": "15d8b55ff02454669db92ad0c5c938051a90adbb1bc18f6f8172cbc73ecd0895", + "src/signplus/models/__init__.py": "c325dcf74c19a599816e7c034850dc8d408f9414f94e3a3a5c422acc0cf5022e", + "src/signplus/models/add_annotation_request.py": "b281be5de951a6bb60a8f6732d295ab0b8f2325005d09c066ef89fef7176b308", + "src/signplus/models/add_envelope_document_request.py": "23e948886a3c7d17cd24aeaa8e2c3807250288c860a9a0ee439fa7ecc17c3a2f", + "src/signplus/models/add_envelope_signing_steps_request.py": "6f1aea96c1678c307ec4a8def7e1442f77e0ac5682888fa62795c0ab85ec1c36", + "src/signplus/models/add_template_document_request.py": "1cbc89c1f47dc1f44b9a76da847b42e04a0a33a12260a0750fb923fbdd80a172", + "src/signplus/models/add_template_signing_steps_request.py": "b434544930b84c9f460ba71c042c2b5ab008d21da4b8d60fc80a0947a1650f75", + "src/signplus/models/annotation.py": "9e215287b3737558fad11f644efe4733f3c2552eef560c8123b6fcd86afba16b", + "src/signplus/models/annotation_checkbox.py": "3726dc2c744260af73c6d22df213ff62b7ab88fb3515e9feb4a0dcded92bea51", + "src/signplus/models/annotation_checkbox_style.py": "53a379a275c3290174844e9a1e0197f8f3c09eb4e46af1a02e02a55b1156ec02", + "src/signplus/models/annotation_date_time.py": "c2fe14c2c5d0b2a99c653c76736d446fe732e570ee531512a46adc875a46d800", + "src/signplus/models/annotation_date_time_format.py": "d2f8026c2e5f2766e201cd2ee7fb4b0c45f56445dce8c03db9ffa4963a6f9ca7", + "src/signplus/models/annotation_font.py": "85792a792831bdd15fddb3d362223da6902aec8febd70a4147d5c84594e9b934", + "src/signplus/models/annotation_font_family.py": "a5f5b09fc0e5817b8b2655eae4cd49971e2accefbfa2e9667d6d7b8f56a3871b", + "src/signplus/models/annotation_initials.py": "56aae8ba61a398ee061b933ab56af596a3681f9db2e0e0dae7ae4beb4a5173ff", + "src/signplus/models/annotation_signature.py": "15a7381d3ef559ba3a31a601cd772dcae22120c39a13dba8330e254f03640372", + "src/signplus/models/annotation_text.py": "3329bb1a6da771e98451aea5dc3413d922b25aefc4f3453fdbc9fc25f55bfd29", + "src/signplus/models/annotation_type.py": "d67c718b15a0529e79731699ee3caff0094c0442d2d137500029def9197ce8bc", + "src/signplus/models/attachment_placeholder.py": "4dcfbb178052319414e42a41c3b62e8ec5e8e0481facc737fdbe8e7a1cbf7dfa", + "src/signplus/models/attachment_placeholder_file.py": "fa88b0351ef7349c8c7976dc5ea4ad5c814d3b8259915e6d5f08ef892ac3d24e", + "src/signplus/models/attachment_placeholder_request.py": "d5da366121d7b8c7c51cae1bf050da5608fcef7091f00eabe49652298a9914f3", + "src/signplus/models/attachment_placeholders_per_recipient.py": "0072071f43657660d3b303a377907b5299bf5cf73ae0742d2f33cdfa5070dbd5", + "src/signplus/models/attachment_settings.py": "14c0aede8e11bc6c05afdf63d4efd8063e31cf989f7cfb77ccde2afa086a6037", + "src/signplus/models/create_envelope_from_template_request.py": "39a3b65fc35a2e20f22ffada6f33037fa121f949c8bce154458d177506e7abf3", + "src/signplus/models/create_envelope_request.py": "150e2bee5d698d764836442d648f1fceda4fb3eae4e247de2737336562ea81da", + "src/signplus/models/create_template_request.py": "5a2f45f6f7ec9b5e0f2b5986ee4a62bcf08fc841e952b22b7f1c4fc7d446e82f", + "src/signplus/models/create_webhook_request.py": "ae09a1996354d6c8cb421e27c5ae8188b5bd711df84299295747d5f7120edb0f", + "src/signplus/models/document.py": "b0097e2f80910be1395502f748376c16b6725659c3f64bd786a2a8eccd2adbc0", + "src/signplus/models/dynamic_field.py": "6844cf2bfada72bd51517fbac65dcba25ae8e5310e03898b9911e8a556ce9077", + "src/signplus/models/envelope.py": "26ae524026947c97c591416339e339b4f7bc0b05b30f5f296072830af62ab91d", + "src/signplus/models/envelope_attachments.py": "c9711fd0f871c34b0861f757b85a77c4130b457cff2db70766f146b04f1c795b", + "src/signplus/models/envelope_flow_type.py": "d4a846b108bb8c4a6676e3425e894d4f398d7bc6c043e0db34fc4b8088715336", + "src/signplus/models/envelope_legality_level.py": "6f9b5ac3a2bceca8d275f42aed6d84e696ee5a83fef60c575348b19eea1e0656", + "src/signplus/models/envelope_notification.py": "b44481bf531c495b0ff4501114ea41f8cccc5f8181559fa491286dcd7f220232", + "src/signplus/models/envelope_order_field.py": "9845d0c30da4d39c7add7e5db3bd71428a734f7126ffd56db84b67f3b2816b6b", + "src/signplus/models/envelope_status.py": "bf7c7a285468fc23dbcf13efbba9752d5dc6f0ae64ccfcf3500463d7bf94c662", + "src/signplus/models/list_envelope_document_annotations_response.py": "a3289c7798b471f67da6a474b4fc72e98534df05737440e7727425e6cce4d092", + "src/signplus/models/list_envelope_documents_response.py": "d50dbd27d93fc0f2e2c1a5f6fb569e1ad240be42b8b6b3ec8140755a89e4fd84", + "src/signplus/models/list_envelopes_request.py": "8cd905e9ed577adcd621d09108468e88124a8798dd74298a0e4da6e23e9741b5", + "src/signplus/models/list_envelopes_response.py": "11845f746bf14143a40a57a132ed7738dbdfc7dd1f6440c62c282196a4f0d021", + "src/signplus/models/list_template_annotations_response.py": "f8d52ab24c613f2f26783eb98cd726182a4781da3394da06075493488d72dad5", + "src/signplus/models/list_template_document_annotations_response.py": "1f1fb0defe7efed8079b887e5e9cb2f005e9271a3d1ce7c494411304fa234a8a", + "src/signplus/models/list_template_documents_response.py": "e876f02f77ff99f9912f04035c42a8f5e30836c7dbe57634ec29150b49f4a5a3", + "src/signplus/models/list_templates_request.py": "4811cd4655ac0856b70771c36e6078309f55dbf28a06004727533ca3a844820a", + "src/signplus/models/list_templates_response.py": "ba67287563d609b14c590d06cde1daaf36e19f0a8c1305e6d60aceb46b6b171b", + "src/signplus/models/list_webhooks_request.py": "cd2fc23141fbaa1d1c5498cbed5db816d5d52dda966e13990a45e393cc614486", + "src/signplus/models/list_webhooks_response.py": "b5558f02d92461c697e139631f7d007a725c80381a16dfebdc791133ca7d9d0e", + "src/signplus/models/page.py": "f56c8c93055aa56cb45dd52f6c9365a4bf74bd3f514da2528c0e38e8d2a32062", + "src/signplus/models/recipient.py": "79041fab70448687f273a0e1b3ae52157663b99f78294badd5a14446bb91800e", + "src/signplus/models/recipient_role.py": "4040dc54ef6aa2242c9fce0e2d5fc2b22db0c51fdfffde71e724060979b4fd14", + "src/signplus/models/recipient_verification.py": "cfdde4989102302ba6af6dffed74853a98563c2371907e9bc054ee167d9e3367", + "src/signplus/models/recipient_verification_type.py": "4102feabfe996f50c5f703cf5c4158090a11630357e694c573ea3686e34c92e7", + "src/signplus/models/rename_envelope_request.py": "a0ab33f95c9ed6d9d2f5d33758f7fb20817f94f1c66f17ed90c3a40d481623a6", + "src/signplus/models/rename_template_request.py": "ef62f6eda949e5d765765247af39298c1e8413cb9503465c76fefcadb8aaa424", + "src/signplus/models/set_envelope_attachments_placeholders_request.py": "f072bbbbd1f9fe4ea272b9ff031c5a7e4b33f57e12692cceb33998331e703b54", + "src/signplus/models/set_envelope_attachments_settings_request.py": "5503bab1c2f8f4f04086a853b7372d74a830a1bacfbeea8c74c5cb6381df802d", + "src/signplus/models/set_envelope_comment_request.py": "823b165c1c63e1099b5892b86981779b588095090c29cab52b928eab8a985966", + "src/signplus/models/set_envelope_dynamic_fields_request.py": "241ce08cbb753676773151799b47312ecaf6ffa0a83cd70e5a8820a3b24a0ab8", + "src/signplus/models/set_envelope_expiration_request.py": "efa1f243dfd50ebe5eea144e8622faad857d4f9a8093e439287bac27449fc063", + "src/signplus/models/set_envelope_legality_level_request.py": "795648e81534f512d64494bd778ad701f6de9461a04261ed5a59e38aedda28f3", + "src/signplus/models/set_template_comment_request.py": "480ad1226570c0dc4e28730e561b4b3966213e00ba9ff95eb5b89afff8483f62", + "src/signplus/models/signing_step.py": "f4b57ca5dc417e907de745923592abdeac09c384cf3c8dd1a08083c3ac94e924", + "src/signplus/models/template.py": "5490681084f9769a14695e4dd68086dcee6e375f7b10140e94f44f08aed41aaf", + "src/signplus/models/template_order_field.py": "49b05cafd722caa15d8ea4cdc05cc36c0deedf7a6f6552ec5c020f573ff04457", + "src/signplus/models/template_recipient.py": "16b4978fdce2a1e90b4aa6c2a5fc5c7a352fad60691a938bd5778a50c331f516", + "src/signplus/models/template_recipient_role.py": "98c1204d37044df2f4b6b424eae7e46ffe6b35d5e31c2a837c9287a21d3ba4e2", + "src/signplus/models/template_signing_step.py": "fa74ce3983d8cd26dbd41a7cbde103dea701f61711d762b0c905f72427f3a5dd", + "src/signplus/models/utils/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "src/signplus/models/utils/base_error.py": "dd6e081bb478edba5c93940540ff33ce9880b671b45b90f0f1fc2cc81cce1453", + "src/signplus/models/utils/base_model.py": "9401a383373d07378da754091de732cd2722dc202ea13bc792a7b802b141db86", + "src/signplus/models/utils/cast_models.py": "65c2a5043fa0178bee0063c944b74d6e24bcbbc77f13716029d0318ab18a24e6", + "src/signplus/models/utils/json_map.py": "14f2b84ad1a0f95098cfc8cbd8dad350995eb4995547d67096fad10b6d08f8c7", + "src/signplus/models/utils/one_of_base_model.py": "5c9d51db7bf2671b50ba7281cd73fac0ae899718fec2511a997063e9932549e6", + "src/signplus/models/utils/sentinel.py": "e52b9ac51a9898f65230fb009b60a809e72f646c559ca78d615931b0c0dae466", + "src/signplus/models/webhook.py": "c127dce617144c79029bd5425673d228e5073230ac29fc7964fd64e2ef346497", + "src/signplus/models/webhook_event.py": "9830c8da368838b2af51520085b88f1d4aa341bf6939f58ea631d7fb668c301b", + "src/signplus/net/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "src/signplus/net/environment/__init__.py": "0c5ed4bcd5c7423b21f2029436abc728a0f5d223e7467344784bd47afd1cdec0", + "src/signplus/net/environment/environment.py": "e8085a0378f9b901031d477f4be014a0ebeb0a97820946829b4d73a6422be9bd", + "src/signplus/net/headers/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "src/signplus/net/headers/access_token_auth.py": "3eda4da03357b122848f8c3bf4786e21d406c0c67a71a1f208a4c28d0835893a", + "src/signplus/net/headers/base_header.py": "0c40412e64e8c34317a13663ddee36137d31b0dbbea38c5eb07ef146f70fe466", + "src/signplus/net/request_chain/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "src/signplus/net/request_chain/handlers/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "src/signplus/net/request_chain/handlers/base_handler.py": "5ff9cdc332de0131ce8e4b5052530b28c863eb9f381ece0f145da3b2cbf20fa5", + "src/signplus/net/request_chain/handlers/http_handler.py": "a736865ee8e8585b67595af46e791fb8d610cac12522b9f61ed73c38425d5e13", + "src/signplus/net/request_chain/handlers/retry_handler.py": "ec6703c6299aaacca84e009a38aed8b8f498b004922154ca3c17fcdbd0208378", + "src/signplus/net/request_chain/request_chain.py": "b21ebb0d8f8018887332570ac4610f16e7268dca0b2e73408a724901165bace4", + "src/signplus/net/sdk_config.py": "4fde62488a5d16513783f735cd0cef2089edd04e831127c935a070ff17000e58", + "src/signplus/net/transport/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "src/signplus/net/transport/api_error.py": "6df36d8aa330fd3b8aca0b34cc525ad4f131e55fe9fffa14e6d690b168400d7b", + "src/signplus/net/transport/request.py": "d04b817c76eee3b345c2c97db44223c1475ad55599faaa3cebb2a8b39b026eba", + "src/signplus/net/transport/request_error.py": "962c1e627288694eb31644f85474f32a540367c382b34119e74adfc52d7fdf06", + "src/signplus/net/transport/response.py": "27b0834b80f907aab8a7d2c91e4e6c6646fdad69ce67eece63c8af8cc8bcc4a1", + "src/signplus/net/transport/serializer.py": "05bd732248a8c0fdcb9548a31f33876dd022acc81d19a8011341b7e2cba6a2dd", + "src/signplus/net/transport/utils.py": "734ea9f9838b85ca9a0b7d8d82c65b56f73324fb02bd9693a60f1b54e4f085da", + "src/signplus/sdk.py": "d1a8f3d28ef1067b690fae5c9a70bf7868f24e0321049333cec66e86e3ad3394", + "src/signplus/sdk_async.py": "9222855f805cee42812148c4b3b1251a13661e64555eec2a89685fab5445750c", + "src/signplus/services/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "src/signplus/services/async_/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "src/signplus/services/async_/signplus.py": "3a69c703c890fe21286fc09187f3672acdd51f27dd68e28ac530390d5e908bce", + "src/signplus/services/async_/utils/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "src/signplus/services/async_/utils/to_async.py": "2cb85fd85bcfa814b70ca92e47479d3e486e2e48ec266fc74694854f3965c582", + "src/signplus/services/signplus.py": "2bcb68fcf8c0f7d61deb31eb349705840d62ae5a28bffdca72bd1338bbad75fb", + "src/signplus/services/utils/__init__.py": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", + "src/signplus/services/utils/base_service.py": "1ce712644adcb265a49ad738ee880366ac3dba37f7a10f78c57cb1191a2aacbd", + "src/signplus/services/utils/default_headers.py": "8b2763f889d8da9febef2c1f8d846177aff0faf03e8978e91c0b18d8811bdf6b", + "src/signplus/services/utils/validator.py": "25e2c20d761d6a8528b4df98545c596e9c309d448e502836f29b0a74e47727ff" + } } diff --git a/LICENSE b/LICENSE index 2be0553..3cef8a0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2025 +Copyright (c) 2026 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/PyPI_README.md b/PyPI_README.md index 83dd200..aa5ae21 100644 --- a/PyPI_README.md +++ b/PyPI_README.md @@ -1,13 +1,11 @@ -# Signplus Python SDK 1.4.0 +# Signplus Python SDK 3.1.0 Welcome to the Signplus SDK documentation. This guide will help you get started with integrating and using the Signplus SDK in your project. -[![This SDK was generated by liblab](https://raw.githubusercontent.com/liblaber/liblab-assets/main/assets/built-by-liblab-icon.svg)](https://liblab.com/?utm_source=readme) - ## Versions - API version: `2.5.0` -- SDK version: `1.4.0` +- SDK version: `3.1.0` ## About the API @@ -26,13 +24,13 @@ Integrate legally-binding electronic signature to your workflow - [Models](#models) - [License](#license) -## Setup & Configuration +# Setup & Configuration -### Supported Language Versions +## Supported Language Versions This SDK is compatible with the following versions: `Python >= 3.7` -### Installation +## Installation To get started with the SDK, we recommend installing using `pip`: @@ -40,6 +38,12 @@ To get started with the SDK, we recommend installing using `pip`: pip install signplus-python ``` +If you are using Python 3, you can use `pip3` instead: + +```bash +pip3 install signplus-python +``` + ## Authentication ### Access Token Authentication diff --git a/README.md b/README.md index 789fac7..6751ff0 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,11 @@ -# Signplus Python SDK 1.4.0 +# Signplus Python SDK 3.1.0 Welcome to the Signplus SDK documentation. This guide will help you get started with integrating and using the Signplus SDK in your project. -[![This SDK was generated by liblab](https://raw.githubusercontent.com/liblaber/liblab-assets/main/assets/built-by-liblab-icon.svg)](https://liblab.com/?utm_source=readme) - ## Versions - API version: `2.5.0` -- SDK version: `1.4.0` +- SDK version: `3.1.0` ## About the API @@ -27,13 +25,13 @@ Integrate legally-binding electronic signature to your workflow - [Models](#models) - [License](#license) -## Setup & Configuration +# Setup & Configuration -### Supported Language Versions +## Supported Language Versions This SDK is compatible with the following versions: `Python >= 3.7` -### Installation +## Installation To get started with the SDK, we recommend installing using `pip`: @@ -41,6 +39,12 @@ To get started with the SDK, we recommend installing using `pip`: pip install signplus-python ``` +If you are using Python 3, you can use `pip3` instead: + +```bash +pip3 install signplus-python +``` + ## Authentication ### Access Token Authentication diff --git a/documentation/models/AddAnnotationRequest.md b/documentation/models/AddAnnotationRequest.md index cf21929..56d67c4 100644 --- a/documentation/models/AddAnnotationRequest.md +++ b/documentation/models/AddAnnotationRequest.md @@ -2,19 +2,19 @@ **Properties** -| Name | Type | Required | Description | -| :----------- | :------------------ | :------- | :---------------------------------------------------------------------------------------------- | -| document_id | str | ✅ | ID of the document | -| page | int | ✅ | Page number where the annotation is placed | -| x | float | ✅ | X coordinate of the annotation (in % of the page width from 0 to 100) from the top left corner | -| y | float | ✅ | Y coordinate of the annotation (in % of the page height from 0 to 100) from the top left corner | -| width | float | ✅ | Width of the annotation (in % of the page width from 0 to 100) | -| height | float | ✅ | Height of the annotation (in % of the page height from 0 to 100) | -| type\_ | AnnotationType | ✅ | Type of the annotation | -| recipient_id | str | ❌ | ID of the recipient | -| required | bool | ❌ | | -| signature | AnnotationSignature | ❌ | Signature annotation (null if annotation is not a signature) | -| initials | AnnotationInitials | ❌ | Initials annotation (null if annotation is not initials) | -| text | AnnotationText | ❌ | Text annotation (null if annotation is not a text) | -| datetime\_ | AnnotationDateTime | ❌ | Date annotation (null if annotation is not a date) | -| checkbox | AnnotationCheckbox | ❌ | Checkbox annotation (null if annotation is not a checkbox) | +| Name | Type | Required | Description | +| :----------- | :-------------------------------------------- | :------- | :---------------------------------------------------------------------------------------------- | +| document_id | str | ✅ | ID of the document | +| page | int | ✅ | Page number where the annotation is placed | +| x | float | ✅ | X coordinate of the annotation (in % of the page width from 0 to 100) from the top left corner | +| y | float | ✅ | Y coordinate of the annotation (in % of the page height from 0 to 100) from the top left corner | +| width | float | ✅ | Width of the annotation (in % of the page width from 0 to 100) | +| height | float | ✅ | Height of the annotation (in % of the page height from 0 to 100) | +| type\_ | [AnnotationType](AnnotationType.md) | ✅ | Type of the annotation | +| recipient_id | str | ❌ | ID of the recipient | +| required | bool | ❌ | | +| signature | [AnnotationSignature](AnnotationSignature.md) | ❌ | Signature annotation (null if annotation is not a signature) | +| initials | [AnnotationInitials](AnnotationInitials.md) | ❌ | Initials annotation (null if annotation is not initials) | +| text | [AnnotationText](AnnotationText.md) | ❌ | Text annotation (null if annotation is not a text) | +| datetime\_ | [AnnotationDateTime](AnnotationDateTime.md) | ❌ | Date annotation (null if annotation is not a date) | +| checkbox | [AnnotationCheckbox](AnnotationCheckbox.md) | ❌ | Checkbox annotation (null if annotation is not a checkbox) | diff --git a/documentation/models/AddEnvelopeSigningStepsRequest.md b/documentation/models/AddEnvelopeSigningStepsRequest.md index 5de9bec..0331d2f 100644 --- a/documentation/models/AddEnvelopeSigningStepsRequest.md +++ b/documentation/models/AddEnvelopeSigningStepsRequest.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :------------ | :---------------- | :------- | :-------------------- | -| signing_steps | List[SigningStep] | ❌ | List of signing steps | +| Name | Type | Required | Description | +| :------------ | :---------------------------------- | :------- | :-------------------- | +| signing_steps | List[[SigningStep](SigningStep.md)] | ❌ | List of signing steps | diff --git a/documentation/models/AddTemplateSigningStepsRequest.md b/documentation/models/AddTemplateSigningStepsRequest.md index a97f23e..3ba0dc1 100644 --- a/documentation/models/AddTemplateSigningStepsRequest.md +++ b/documentation/models/AddTemplateSigningStepsRequest.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :------------ | :------------------------ | :------- | :-------------------- | -| signing_steps | List[TemplateSigningStep] | ✅ | List of signing steps | +| Name | Type | Required | Description | +| :------------ | :-------------------------------------------------- | :------- | :-------------------- | +| signing_steps | List[[TemplateSigningStep](TemplateSigningStep.md)] | ✅ | List of signing steps | diff --git a/documentation/models/Annotation.md b/documentation/models/Annotation.md index 0102e4a..e75e119 100644 --- a/documentation/models/Annotation.md +++ b/documentation/models/Annotation.md @@ -2,20 +2,20 @@ **Properties** -| Name | Type | Required | Description | -| :----------- | :------------------ | :------- | :---------------------------------------------------------------------------------------------- | -| id\_ | str | ❌ | Unique identifier of the annotation | -| recipient_id | str | ❌ | ID of the recipient | -| document_id | str | ❌ | ID of the document | -| page | int | ❌ | Page number where the annotation is placed | -| x | float | ❌ | X coordinate of the annotation (in % of the page width from 0 to 100) from the top left corner | -| y | float | ❌ | Y coordinate of the annotation (in % of the page height from 0 to 100) from the top left corner | -| width | float | ❌ | Width of the annotation (in % of the page width from 0 to 100) | -| height | float | ❌ | Height of the annotation (in % of the page height from 0 to 100) | -| required | bool | ❌ | Whether the annotation is required | -| type\_ | AnnotationType | ❌ | Type of the annotation | -| signature | AnnotationSignature | ❌ | Signature annotation (null if annotation is not a signature) | -| initials | AnnotationInitials | ❌ | Initials annotation (null if annotation is not initials) | -| text | AnnotationText | ❌ | Text annotation (null if annotation is not a text) | -| datetime\_ | AnnotationDateTime | ❌ | Date annotation (null if annotation is not a date) | -| checkbox | AnnotationCheckbox | ❌ | Checkbox annotation (null if annotation is not a checkbox) | +| Name | Type | Required | Description | +| :----------- | :-------------------------------------------- | :------- | :---------------------------------------------------------------------------------------------- | +| id\_ | str | ❌ | Unique identifier of the annotation | +| recipient_id | str | ❌ | ID of the recipient | +| document_id | str | ❌ | ID of the document | +| page | int | ❌ | Page number where the annotation is placed | +| x | float | ❌ | X coordinate of the annotation (in % of the page width from 0 to 100) from the top left corner | +| y | float | ❌ | Y coordinate of the annotation (in % of the page height from 0 to 100) from the top left corner | +| width | float | ❌ | Width of the annotation (in % of the page width from 0 to 100) | +| height | float | ❌ | Height of the annotation (in % of the page height from 0 to 100) | +| required | bool | ❌ | Whether the annotation is required | +| type\_ | [AnnotationType](AnnotationType.md) | ❌ | Type of the annotation | +| signature | [AnnotationSignature](AnnotationSignature.md) | ❌ | Signature annotation (null if annotation is not a signature) | +| initials | [AnnotationInitials](AnnotationInitials.md) | ❌ | Initials annotation (null if annotation is not initials) | +| text | [AnnotationText](AnnotationText.md) | ❌ | Text annotation (null if annotation is not a text) | +| datetime\_ | [AnnotationDateTime](AnnotationDateTime.md) | ❌ | Date annotation (null if annotation is not a date) | +| checkbox | [AnnotationCheckbox](AnnotationCheckbox.md) | ❌ | Checkbox annotation (null if annotation is not a checkbox) | diff --git a/documentation/models/AnnotationCheckbox.md b/documentation/models/AnnotationCheckbox.md index 4af837f..60e565a 100644 --- a/documentation/models/AnnotationCheckbox.md +++ b/documentation/models/AnnotationCheckbox.md @@ -4,7 +4,7 @@ Checkbox annotation (null if annotation is not a checkbox) **Properties** -| Name | Type | Required | Description | -| :------ | :---------------------- | :------- | :------------------------------ | -| checked | bool | ❌ | Whether the checkbox is checked | -| style | AnnotationCheckboxStyle | ❌ | Style of the checkbox | +| Name | Type | Required | Description | +| :------ | :---------------------------------------------------- | :------- | :------------------------------ | +| checked | bool | ❌ | Whether the checkbox is checked | +| style | [AnnotationCheckboxStyle](AnnotationCheckboxStyle.md) | ❌ | Style of the checkbox | diff --git a/documentation/models/AnnotationDateTime.md b/documentation/models/AnnotationDateTime.md index 205181e..a064816 100644 --- a/documentation/models/AnnotationDateTime.md +++ b/documentation/models/AnnotationDateTime.md @@ -4,12 +4,12 @@ Date annotation (null if annotation is not a date) **Properties** -| Name | Type | Required | Description | -| :-------- | :----------------------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| size | float | ❌ | Font size of the text in pt | -| font | AnnotationFont | ❌ | | -| color | str | ❌ | Color of the text in hex format | -| auto_fill | bool | ❌ | Whether the date should be automatically filled | -| timezone | str | ❌ | Timezone of the date | -| timestamp | int | ❌ | Unix timestamp of the date | -| format | AnnotationDateTimeFormat | ❌ | Format of the date time (DMY_NUMERIC_SLASH is day/month/year with slashes, MDY_NUMERIC_SLASH is month/day/year with slashes, YMD_NUMERIC_SLASH is year/month/day with slashes, DMY_NUMERIC_DASH_SHORT is day/month/year with dashes, DMY_NUMERIC_DASH is day/month/year with dashes, YMD_NUMERIC_DASH is year/month/day with dashes, MDY_TEXT_DASH_SHORT is month/day/year with dashes, MDY_TEXT_SPACE_SHORT is month/day/year with spaces, MDY_TEXT_SPACE is month/day/year with spaces) | +| Name | Type | Required | Description | +| :-------- | :------------------------------------------------------ | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| size | float | ❌ | Font size of the text in pt | +| font | [AnnotationFont](AnnotationFont.md) | ❌ | | +| color | str | ❌ | Color of the text in hex format | +| auto_fill | bool | ❌ | Whether the date should be automatically filled | +| timezone | str | ❌ | Timezone of the date | +| timestamp | int | ❌ | Unix timestamp of the date | +| format | [AnnotationDateTimeFormat](AnnotationDateTimeFormat.md) | ❌ | Format of the date time (DMY_NUMERIC_SLASH is day/month/year with slashes, MDY_NUMERIC_SLASH is month/day/year with slashes, YMD_NUMERIC_SLASH is year/month/day with slashes, DMY_NUMERIC_DASH_SHORT is day/month/year with dashes, DMY_NUMERIC_DASH is day/month/year with dashes, YMD_NUMERIC_DASH is year/month/day with dashes, MDY_TEXT_DASH_SHORT is month/day/year with dashes, MDY_TEXT_SPACE_SHORT is month/day/year with spaces, MDY_TEXT_SPACE is month/day/year with spaces) | diff --git a/documentation/models/AnnotationFont.md b/documentation/models/AnnotationFont.md index 3be9df8..3f4f6c7 100644 --- a/documentation/models/AnnotationFont.md +++ b/documentation/models/AnnotationFont.md @@ -2,8 +2,8 @@ **Properties** -| Name | Type | Required | Description | -| :----- | :------------------- | :------- | :------------------------- | -| family | AnnotationFontFamily | ❌ | Font family of the text | -| italic | bool | ❌ | Whether the text is italic | -| bold | bool | ❌ | Whether the text is bold | +| Name | Type | Required | Description | +| :----- | :---------------------------------------------- | :------- | :------------------------- | +| family | [AnnotationFontFamily](AnnotationFontFamily.md) | ❌ | Font family of the text | +| italic | bool | ❌ | Whether the text is italic | +| bold | bool | ❌ | Whether the text is bold | diff --git a/documentation/models/AnnotationText.md b/documentation/models/AnnotationText.md index e50f4fd..3dd70eb 100644 --- a/documentation/models/AnnotationText.md +++ b/documentation/models/AnnotationText.md @@ -4,11 +4,11 @@ Text annotation (null if annotation is not a text) **Properties** -| Name | Type | Required | Description | -| :----------------- | :------------- | :------- | :--------------------------------- | -| size | float | ❌ | Font size of the text in pt | -| color | float | ❌ | Text color in 32bit representation | -| value | str | ❌ | Text content of the annotation | -| tooltip | str | ❌ | Tooltip of the annotation | -| dynamic_field_name | str | ❌ | Name of the dynamic field | -| font | AnnotationFont | ❌ | | +| Name | Type | Required | Description | +| :----------------- | :---------------------------------- | :------- | :--------------------------------- | +| size | float | ❌ | Font size of the text in pt | +| color | float | ❌ | Text color in 32bit representation | +| value | str | ❌ | Text content of the annotation | +| tooltip | str | ❌ | Tooltip of the annotation | +| dynamic_field_name | str | ❌ | Name of the dynamic field | +| font | [AnnotationFont](AnnotationFont.md) | ❌ | | diff --git a/documentation/models/AttachmentPlaceholder.md b/documentation/models/AttachmentPlaceholder.md index 0519d12..74caf17 100644 --- a/documentation/models/AttachmentPlaceholder.md +++ b/documentation/models/AttachmentPlaceholder.md @@ -2,12 +2,12 @@ **Properties** -| Name | Type | Required | Description | -| :----------- | :------------------------------ | :------- | :--------------------------------------------------------- | -| recipient_id | str | ❌ | ID of the recipient | -| id\_ | str | ❌ | ID of the attachment placeholder | -| name | str | ❌ | Name of the attachment placeholder | -| hint | str | ❌ | Hint of the attachment placeholder | -| required | bool | ❌ | Whether the attachment placeholder is required | -| multiple | bool | ❌ | Whether the attachment placeholder can have multiple files | -| files | List[AttachmentPlaceholderFile] | ❌ | | +| Name | Type | Required | Description | +| :----------- | :-------------------------------------------------------------- | :------- | :--------------------------------------------------------- | +| recipient_id | str | ❌ | ID of the recipient | +| id\_ | str | ❌ | ID of the attachment placeholder | +| name | str | ❌ | Name of the attachment placeholder | +| hint | str | ❌ | Hint of the attachment placeholder | +| required | bool | ❌ | Whether the attachment placeholder is required | +| multiple | bool | ❌ | Whether the attachment placeholder can have multiple files | +| files | List[[AttachmentPlaceholderFile](AttachmentPlaceholderFile.md)] | ❌ | | diff --git a/documentation/models/AttachmentPlaceholdersPerRecipient.md b/documentation/models/AttachmentPlaceholdersPerRecipient.md index b8880a3..569a433 100644 --- a/documentation/models/AttachmentPlaceholdersPerRecipient.md +++ b/documentation/models/AttachmentPlaceholdersPerRecipient.md @@ -2,8 +2,8 @@ **Properties** -| Name | Type | Required | Description | -| :------------- | :-------------------------- | :------- | :-------------------- | -| recipient_id | str | ❌ | ID of the recipient | -| recipient_name | str | ❌ | Name of the recipient | -| placeholders | List[AttachmentPlaceholder] | ❌ | | +| Name | Type | Required | Description | +| :------------- | :------------------------------------------------------ | :------- | :-------------------- | +| recipient_id | str | ❌ | ID of the recipient | +| recipient_name | str | ❌ | Name of the recipient | +| placeholders | List[[AttachmentPlaceholder](AttachmentPlaceholder.md)] | ❌ | | diff --git a/documentation/models/CreateEnvelopeRequest.md b/documentation/models/CreateEnvelopeRequest.md index 3cb2bdd..5d1166a 100644 --- a/documentation/models/CreateEnvelopeRequest.md +++ b/documentation/models/CreateEnvelopeRequest.md @@ -2,10 +2,10 @@ **Properties** -| Name | Type | Required | Description | -| :------------- | :-------------------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| name | str | ✅ | Name of the envelope | -| legality_level | EnvelopeLegalityLevel | ✅ | Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes) | -| expires_at | int | ❌ | Unix timestamp of the expiration date | -| comment | str | ❌ | Comment for the envelope | -| sandbox | bool | ❌ | Whether the envelope is created in sandbox mode | +| Name | Type | Required | Description | +| :------------- | :------------------------------------------------ | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | str | ✅ | Name of the envelope | +| legality_level | [EnvelopeLegalityLevel](EnvelopeLegalityLevel.md) | ✅ | Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes) | +| expires_at | int | ❌ | Unix timestamp of the expiration date | +| comment | str | ❌ | Comment for the envelope | +| sandbox | bool | ❌ | Whether the envelope is created in sandbox mode | diff --git a/documentation/models/CreateWebhookRequest.md b/documentation/models/CreateWebhookRequest.md index c92ad94..f40e4ba 100644 --- a/documentation/models/CreateWebhookRequest.md +++ b/documentation/models/CreateWebhookRequest.md @@ -2,7 +2,7 @@ **Properties** -| Name | Type | Required | Description | -| :----- | :----------- | :------- | :------------------------ | -| event | WebhookEvent | ✅ | Event of the webhook | -| target | str | ✅ | URL of the webhook target | +| Name | Type | Required | Description | +| :----- | :------------------------------ | :------- | :------------------------ | +| event | [WebhookEvent](WebhookEvent.md) | ✅ | Event of the webhook | +| target | str | ✅ | URL of the webhook target | diff --git a/documentation/models/Document.md b/documentation/models/Document.md index ae52c8a..7706cbd 100644 --- a/documentation/models/Document.md +++ b/documentation/models/Document.md @@ -2,10 +2,10 @@ **Properties** -| Name | Type | Required | Description | -| :--------- | :--------- | :------- | :-------------------------------- | -| id\_ | str | ❌ | Unique identifier of the document | -| name | str | ❌ | Name of the document | -| filename | str | ❌ | Filename of the document | -| page_count | int | ❌ | Number of pages in the document | -| pages | List[Page] | ❌ | List of pages in the document | +| Name | Type | Required | Description | +| :--------- | :-------------------- | :------- | :-------------------------------- | +| id\_ | str | ❌ | Unique identifier of the document | +| name | str | ❌ | Name of the document | +| filename | str | ❌ | Filename of the document | +| page_count | int | ❌ | Number of pages in the document | +| pages | List[[Page](Page.md)] | ❌ | List of pages in the document | diff --git a/documentation/models/Envelope.md b/documentation/models/Envelope.md index e541221..119d65e 100644 --- a/documentation/models/Envelope.md +++ b/documentation/models/Envelope.md @@ -2,21 +2,21 @@ **Properties** -| Name | Type | Required | Description | -| :------------- | :-------------------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| id\_ | str | ❌ | Unique identifier of the envelope | -| name | str | ❌ | Name of the envelope | -| comment | str | ❌ | Comment for the envelope | -| pages | int | ❌ | Total number of pages in the envelope | -| flow_type | EnvelopeFlowType | ❌ | Flow type of the envelope (REQUEST_SIGNATURE is a request for signature, SIGN_MYSELF is a self-signing flow) | -| legality_level | EnvelopeLegalityLevel | ❌ | Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes) | -| status | EnvelopeStatus | ❌ | Status of the envelope | -| created_at | int | ❌ | Unix timestamp of the creation date | -| updated_at | int | ❌ | Unix timestamp of the last modification date | -| expires_at | int | ❌ | Unix timestamp of the expiration date | -| num_recipients | int | ❌ | Number of recipients in the envelope | -| is_duplicable | bool | ❌ | Whether the envelope can be duplicated | -| signing_steps | List[SigningStep] | ❌ | | -| documents | List[Document] | ❌ | | -| notification | EnvelopeNotification | ❌ | | -| attachments | EnvelopeAttachments | ❌ | | +| Name | Type | Required | Description | +| :------------- | :------------------------------------------------ | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| id\_ | str | ❌ | Unique identifier of the envelope | +| name | str | ❌ | Name of the envelope | +| comment | str | ❌ | Comment for the envelope | +| pages | int | ❌ | Total number of pages in the envelope | +| flow_type | [EnvelopeFlowType](EnvelopeFlowType.md) | ❌ | Flow type of the envelope (REQUEST_SIGNATURE is a request for signature, SIGN_MYSELF is a self-signing flow) | +| legality_level | [EnvelopeLegalityLevel](EnvelopeLegalityLevel.md) | ❌ | Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes) | +| status | [EnvelopeStatus](EnvelopeStatus.md) | ❌ | Status of the envelope | +| created_at | int | ❌ | Unix timestamp of the creation date | +| updated_at | int | ❌ | Unix timestamp of the last modification date | +| expires_at | int | ❌ | Unix timestamp of the expiration date | +| num_recipients | int | ❌ | Number of recipients in the envelope | +| is_duplicable | bool | ❌ | Whether the envelope can be duplicated | +| signing_steps | List[[SigningStep](SigningStep.md)] | ❌ | | +| documents | List[[Document](Document.md)] | ❌ | | +| notification | [EnvelopeNotification](EnvelopeNotification.md) | ❌ | | +| attachments | [EnvelopeAttachments](EnvelopeAttachments.md) | ❌ | | diff --git a/documentation/models/EnvelopeAttachments.md b/documentation/models/EnvelopeAttachments.md index c146195..e4f9fa2 100644 --- a/documentation/models/EnvelopeAttachments.md +++ b/documentation/models/EnvelopeAttachments.md @@ -2,7 +2,7 @@ **Properties** -| Name | Type | Required | Description | -| :--------- | :--------------------------------------- | :------- | :---------- | -| settings | AttachmentSettings | ❌ | | -| recipients | List[AttachmentPlaceholdersPerRecipient] | ❌ | | +| Name | Type | Required | Description | +| :--------- | :-------------------------------------------------------------------------------- | :------- | :---------- | +| settings | [AttachmentSettings](AttachmentSettings.md) | ❌ | | +| recipients | List[[AttachmentPlaceholdersPerRecipient](AttachmentPlaceholdersPerRecipient.md)] | ❌ | | diff --git a/documentation/models/ListEnvelopeDocumentAnnotationsResponse.md b/documentation/models/ListEnvelopeDocumentAnnotationsResponse.md index 22b1a4b..85c5bf6 100644 --- a/documentation/models/ListEnvelopeDocumentAnnotationsResponse.md +++ b/documentation/models/ListEnvelopeDocumentAnnotationsResponse.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :---------- | :--------------- | :------- | :---------- | -| annotations | List[Annotation] | ❌ | | +| Name | Type | Required | Description | +| :---------- | :-------------------------------- | :------- | :---------- | +| annotations | List[[Annotation](Annotation.md)] | ❌ | | diff --git a/documentation/models/ListEnvelopeDocumentsResponse.md b/documentation/models/ListEnvelopeDocumentsResponse.md index 9ba191c..8a2ff35 100644 --- a/documentation/models/ListEnvelopeDocumentsResponse.md +++ b/documentation/models/ListEnvelopeDocumentsResponse.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :-------- | :------------- | :------- | :---------- | -| documents | List[Document] | ❌ | | +| Name | Type | Required | Description | +| :-------- | :---------------------------- | :------- | :---------- | +| documents | List[[Document](Document.md)] | ❌ | | diff --git a/documentation/models/ListEnvelopesRequest.md b/documentation/models/ListEnvelopesRequest.md index c69717e..4eae323 100644 --- a/documentation/models/ListEnvelopesRequest.md +++ b/documentation/models/ListEnvelopesRequest.md @@ -2,22 +2,22 @@ **Properties** -| Name | Type | Required | Description | -| :--------------- | :------------------- | :------- | :------------------------------------------------ | -| name | str | ❌ | Name of the envelope | -| tags | List[str] | ❌ | List of tags | -| comment | str | ❌ | Comment of the envelope | -| ids | List[str] | ❌ | List of envelope IDs | -| statuses | List[EnvelopeStatus] | ❌ | List of envelope statuses | -| folder_ids | List[str] | ❌ | List of folder IDs | -| only_root_folder | bool | ❌ | Whether to only list envelopes in the root folder | -| date_from | int | ❌ | Unix timestamp of the start date | -| date_to | int | ❌ | Unix timestamp of the end date | -| uid | str | ❌ | Unique identifier of the user | -| first | int | ❌ | | -| last | int | ❌ | | -| after | str | ❌ | | -| before | str | ❌ | | -| order_field | EnvelopeOrderField | ❌ | Field to order envelopes by | -| ascending | bool | ❌ | Whether to order envelopes in ascending order | -| include_trash | bool | ❌ | Whether to include envelopes in the trash | +| Name | Type | Required | Description | +| :--------------- | :------------------------------------------ | :------- | :------------------------------------------------ | +| name | str | ❌ | Name of the envelope | +| tags | List[str] | ❌ | List of tags | +| comment | str | ❌ | Comment of the envelope | +| ids | List[str] | ❌ | List of envelope IDs | +| statuses | List[[EnvelopeStatus](EnvelopeStatus.md)] | ❌ | List of envelope statuses | +| folder_ids | List[str] | ❌ | List of folder IDs | +| only_root_folder | bool | ❌ | Whether to only list envelopes in the root folder | +| date_from | int | ❌ | Unix timestamp of the start date | +| date_to | int | ❌ | Unix timestamp of the end date | +| uid | str | ❌ | Unique identifier of the user | +| first | int | ❌ | | +| last | int | ❌ | | +| after | str | ❌ | | +| before | str | ❌ | | +| order_field | [EnvelopeOrderField](EnvelopeOrderField.md) | ❌ | Field to order envelopes by | +| ascending | bool | ❌ | Whether to order envelopes in ascending order | +| include_trash | bool | ❌ | Whether to include envelopes in the trash | diff --git a/documentation/models/ListEnvelopesResponse.md b/documentation/models/ListEnvelopesResponse.md index 5821fc7..560d31b 100644 --- a/documentation/models/ListEnvelopesResponse.md +++ b/documentation/models/ListEnvelopesResponse.md @@ -2,8 +2,8 @@ **Properties** -| Name | Type | Required | Description | -| :---------------- | :------------- | :------- | :------------------------------- | -| has_next_page | bool | ❌ | Whether there is a next page | -| has_previous_page | bool | ❌ | Whether there is a previous page | -| envelopes | List[Envelope] | ❌ | | +| Name | Type | Required | Description | +| :---------------- | :---------------------------- | :------- | :------------------------------- | +| has_next_page | bool | ❌ | Whether there is a next page | +| has_previous_page | bool | ❌ | Whether there is a previous page | +| envelopes | List[[Envelope](Envelope.md)] | ❌ | | diff --git a/documentation/models/ListTemplateAnnotationsResponse.md b/documentation/models/ListTemplateAnnotationsResponse.md index 04dd084..2178524 100644 --- a/documentation/models/ListTemplateAnnotationsResponse.md +++ b/documentation/models/ListTemplateAnnotationsResponse.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :---------- | :--------------- | :------- | :---------- | -| annotations | List[Annotation] | ❌ | | +| Name | Type | Required | Description | +| :---------- | :-------------------------------- | :------- | :---------- | +| annotations | List[[Annotation](Annotation.md)] | ❌ | | diff --git a/documentation/models/ListTemplateDocumentAnnotationsResponse.md b/documentation/models/ListTemplateDocumentAnnotationsResponse.md index 4159232..d9b3884 100644 --- a/documentation/models/ListTemplateDocumentAnnotationsResponse.md +++ b/documentation/models/ListTemplateDocumentAnnotationsResponse.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :---------- | :--------------- | :------- | :---------- | -| annotations | List[Annotation] | ❌ | | +| Name | Type | Required | Description | +| :---------- | :-------------------------------- | :------- | :---------- | +| annotations | List[[Annotation](Annotation.md)] | ❌ | | diff --git a/documentation/models/ListTemplateDocumentsResponse.md b/documentation/models/ListTemplateDocumentsResponse.md index 2066d6e..a43c75d 100644 --- a/documentation/models/ListTemplateDocumentsResponse.md +++ b/documentation/models/ListTemplateDocumentsResponse.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :-------- | :------------- | :------- | :---------- | -| documents | List[Document] | ❌ | | +| Name | Type | Required | Description | +| :-------- | :---------------------------- | :------- | :---------- | +| documents | List[[Document](Document.md)] | ❌ | | diff --git a/documentation/models/ListTemplatesRequest.md b/documentation/models/ListTemplatesRequest.md index 51cf549..3e2dfbb 100644 --- a/documentation/models/ListTemplatesRequest.md +++ b/documentation/models/ListTemplatesRequest.md @@ -2,14 +2,14 @@ **Properties** -| Name | Type | Required | Description | -| :---------- | :----------------- | :------- | :-------------------------------------------- | -| name | str | ❌ | Name of the template | -| tags | List[str] | ❌ | List of tag templates | -| ids | List[str] | ❌ | List of templates IDs | -| first | int | ❌ | | -| last | int | ❌ | | -| after | str | ❌ | | -| before | str | ❌ | | -| order_field | TemplateOrderField | ❌ | Field to order templates by | -| ascending | bool | ❌ | Whether to order templates in ascending order | +| Name | Type | Required | Description | +| :---------- | :------------------------------------------ | :------- | :-------------------------------------------- | +| name | str | ❌ | Name of the template | +| tags | List[str] | ❌ | List of tag templates | +| ids | List[str] | ❌ | List of templates IDs | +| first | int | ❌ | | +| last | int | ❌ | | +| after | str | ❌ | | +| before | str | ❌ | | +| order_field | [TemplateOrderField](TemplateOrderField.md) | ❌ | Field to order templates by | +| ascending | bool | ❌ | Whether to order templates in ascending order | diff --git a/documentation/models/ListTemplatesResponse.md b/documentation/models/ListTemplatesResponse.md index 031ce7a..23372ca 100644 --- a/documentation/models/ListTemplatesResponse.md +++ b/documentation/models/ListTemplatesResponse.md @@ -2,8 +2,8 @@ **Properties** -| Name | Type | Required | Description | -| :---------------- | :------------- | :------- | :------------------------------- | -| has_next_page | bool | ❌ | Whether there is a next page | -| has_previous_page | bool | ❌ | Whether there is a previous page | -| templates | List[Template] | ❌ | | +| Name | Type | Required | Description | +| :---------------- | :---------------------------- | :------- | :------------------------------- | +| has_next_page | bool | ❌ | Whether there is a next page | +| has_previous_page | bool | ❌ | Whether there is a previous page | +| templates | List[[Template](Template.md)] | ❌ | | diff --git a/documentation/models/ListWebhooksRequest.md b/documentation/models/ListWebhooksRequest.md index ab5ab2b..ae59f9a 100644 --- a/documentation/models/ListWebhooksRequest.md +++ b/documentation/models/ListWebhooksRequest.md @@ -2,7 +2,7 @@ **Properties** -| Name | Type | Required | Description | -| :--------- | :----------- | :------- | :------------------- | -| webhook_id | str | ❌ | ID of the webhook | -| event | WebhookEvent | ❌ | Event of the webhook | +| Name | Type | Required | Description | +| :--------- | :------------------------------ | :------- | :------------------- | +| webhook_id | str | ❌ | ID of the webhook | +| event | [WebhookEvent](WebhookEvent.md) | ❌ | Event of the webhook | diff --git a/documentation/models/ListWebhooksResponse.md b/documentation/models/ListWebhooksResponse.md index b0ed509..2a50894 100644 --- a/documentation/models/ListWebhooksResponse.md +++ b/documentation/models/ListWebhooksResponse.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :------- | :------------ | :------- | :---------- | -| webhooks | List[Webhook] | ❌ | | +| Name | Type | Required | Description | +| :------- | :-------------------------- | :------- | :---------- | +| webhooks | List[[Webhook](Webhook.md)] | ❌ | | diff --git a/documentation/models/Recipient.md b/documentation/models/Recipient.md index 77970f4..e58ecc1 100644 --- a/documentation/models/Recipient.md +++ b/documentation/models/Recipient.md @@ -2,11 +2,11 @@ **Properties** -| Name | Type | Required | Description | -| :----------- | :-------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| name | str | ✅ | Name of the recipient | -| email | str | ✅ | Email of the recipient | -| role | RecipientRole | ✅ | Role of the recipient (SIGNER signs the document, RECEIVES_COPY receives a copy of the document, IN_PERSON_SIGNER signs the document in person, SENDER sends the document) | -| id\_ | str | ❌ | Unique identifier of the recipient | -| uid | str | ❌ | Unique identifier of the user associated with the recipient | -| verification | RecipientVerification | ❌ | | +| Name | Type | Required | Description | +| :----------- | :------------------------------------------------ | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| name | str | ✅ | Name of the recipient | +| email | str | ✅ | Email of the recipient | +| role | [RecipientRole](RecipientRole.md) | ✅ | Role of the recipient (SIGNER signs the document, RECEIVES_COPY receives a copy of the document, IN_PERSON_SIGNER signs the document in person, SENDER sends the document) | +| id\_ | str | ❌ | Unique identifier of the recipient | +| uid | str | ❌ | Unique identifier of the user associated with the recipient | +| verification | [RecipientVerification](RecipientVerification.md) | ❌ | | diff --git a/documentation/models/RecipientVerification.md b/documentation/models/RecipientVerification.md index 0c3a87a..e841d3c 100644 --- a/documentation/models/RecipientVerification.md +++ b/documentation/models/RecipientVerification.md @@ -2,7 +2,7 @@ **Properties** -| Name | Type | Required | Description | -| :----- | :------------------------ | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| type\_ | RecipientVerificationType | ❌ | Type of verification the recipient must complete before accessing the envelope. - `PASSCODE`: requires a code to be entered. - `SMS`: sends a code via SMS. - `ID_VERIFICATION`: prompts the recipient to complete an automated ID and selfie check. | -| value | str | ❌ | Required for `PASSCODE` and `SMS` verification. - `PASSCODE`: code required by the recipient to sign the document. - `SMS`: recipient's phone number. - `ID_VERIFICATION`: leave empty. | +| Name | Type | Required | Description | +| :----- | :-------------------------------------------------------- | :------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| type\_ | [RecipientVerificationType](RecipientVerificationType.md) | ❌ | Type of verification the recipient must complete before accessing the envelope. - `PASSCODE`: requires a code to be entered. - `SMS`: sends a code via SMS. - `ID_VERIFICATION`: prompts the recipient to complete an automated ID and selfie check. | +| value | str | ❌ | Required for `PASSCODE` and `SMS` verification. - `PASSCODE`: code required by the recipient to sign the document. - `SMS`: recipient's phone number. - `ID_VERIFICATION`: leave empty. | diff --git a/documentation/models/SetEnvelopeAttachmentsPlaceholdersRequest.md b/documentation/models/SetEnvelopeAttachmentsPlaceholdersRequest.md index fe001b1..242b582 100644 --- a/documentation/models/SetEnvelopeAttachmentsPlaceholdersRequest.md +++ b/documentation/models/SetEnvelopeAttachmentsPlaceholdersRequest.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :----------- | :--------------------------------- | :------- | :---------- | -| placeholders | List[AttachmentPlaceholderRequest] | ✅ | | +| Name | Type | Required | Description | +| :----------- | :-------------------------------------------------------------------- | :------- | :---------- | +| placeholders | List[[AttachmentPlaceholderRequest](AttachmentPlaceholderRequest.md)] | ✅ | | diff --git a/documentation/models/SetEnvelopeAttachmentsSettingsRequest.md b/documentation/models/SetEnvelopeAttachmentsSettingsRequest.md index 214f26e..edfdc4a 100644 --- a/documentation/models/SetEnvelopeAttachmentsSettingsRequest.md +++ b/documentation/models/SetEnvelopeAttachmentsSettingsRequest.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :------- | :----------------- | :------- | :---------- | -| settings | AttachmentSettings | ✅ | | +| Name | Type | Required | Description | +| :------- | :------------------------------------------ | :------- | :---------- | +| settings | [AttachmentSettings](AttachmentSettings.md) | ✅ | | diff --git a/documentation/models/SetEnvelopeDynamicFieldsRequest.md b/documentation/models/SetEnvelopeDynamicFieldsRequest.md index de3856f..ef14c34 100644 --- a/documentation/models/SetEnvelopeDynamicFieldsRequest.md +++ b/documentation/models/SetEnvelopeDynamicFieldsRequest.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :------------- | :----------------- | :------- | :--------------------- | -| dynamic_fields | List[DynamicField] | ✅ | List of dynamic fields | +| Name | Type | Required | Description | +| :------------- | :------------------------------------ | :------- | :--------------------- | +| dynamic_fields | List[[DynamicField](DynamicField.md)] | ✅ | List of dynamic fields | diff --git a/documentation/models/SetEnvelopeLegalityLevelRequest.md b/documentation/models/SetEnvelopeLegalityLevelRequest.md index 8cda3e4..8f7b1d9 100644 --- a/documentation/models/SetEnvelopeLegalityLevelRequest.md +++ b/documentation/models/SetEnvelopeLegalityLevelRequest.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :------------- | :-------------------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| legality_level | EnvelopeLegalityLevel | ❌ | Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes) | +| Name | Type | Required | Description | +| :------------- | :------------------------------------------------ | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| legality_level | [EnvelopeLegalityLevel](EnvelopeLegalityLevel.md) | ❌ | Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes) | diff --git a/documentation/models/SigningStep.md b/documentation/models/SigningStep.md index 6c6f00b..7edd4c1 100644 --- a/documentation/models/SigningStep.md +++ b/documentation/models/SigningStep.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :--------- | :-------------- | :------- | :----------------- | -| recipients | List[Recipient] | ❌ | List of recipients | +| Name | Type | Required | Description | +| :--------- | :------------------------------ | :------- | :----------------- | +| recipients | List[[Recipient](Recipient.md)] | ❌ | List of recipients | diff --git a/documentation/models/Template.md b/documentation/models/Template.md index fc1bdaa..45c15ae 100644 --- a/documentation/models/Template.md +++ b/documentation/models/Template.md @@ -2,19 +2,19 @@ **Properties** -| Name | Type | Required | Description | -| :--------------- | :------------------------ | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| id\_ | str | ❌ | Unique identifier of the template | -| name | str | ❌ | Name of the template | -| comment | str | ❌ | Comment for the template | -| pages | int | ❌ | Total number of pages in the template | -| legality_level | EnvelopeLegalityLevel | ❌ | Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes) | -| created_at | int | ❌ | Unix timestamp of the creation date | -| updated_at | int | ❌ | Unix timestamp of the last modification date | -| expiration_delay | int | ❌ | Expiration delay added to the current time when an envelope is created from this template | -| num_recipients | int | ❌ | Number of recipients in the envelope | -| signing_steps | List[TemplateSigningStep] | ❌ | | -| documents | List[Document] | ❌ | | -| notification | EnvelopeNotification | ❌ | | -| dynamic_fields | List[str] | ❌ | List of dynamic fields | -| attachments | EnvelopeAttachments | ❌ | | +| Name | Type | Required | Description | +| :--------------- | :-------------------------------------------------- | :------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| id\_ | str | ❌ | Unique identifier of the template | +| name | str | ❌ | Name of the template | +| comment | str | ❌ | Comment for the template | +| pages | int | ❌ | Total number of pages in the template | +| legality_level | [EnvelopeLegalityLevel](EnvelopeLegalityLevel.md) | ❌ | Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes) | +| created_at | int | ❌ | Unix timestamp of the creation date | +| updated_at | int | ❌ | Unix timestamp of the last modification date | +| expiration_delay | int | ❌ | Expiration delay added to the current time when an envelope is created from this template | +| num_recipients | int | ❌ | Number of recipients in the envelope | +| signing_steps | List[[TemplateSigningStep](TemplateSigningStep.md)] | ❌ | | +| documents | List[[Document](Document.md)] | ❌ | | +| notification | [EnvelopeNotification](EnvelopeNotification.md) | ❌ | | +| dynamic_fields | List[str] | ❌ | List of dynamic fields | +| attachments | [EnvelopeAttachments](EnvelopeAttachments.md) | ❌ | | diff --git a/documentation/models/TemplateRecipient.md b/documentation/models/TemplateRecipient.md index e54055f..35e0c73 100644 --- a/documentation/models/TemplateRecipient.md +++ b/documentation/models/TemplateRecipient.md @@ -2,10 +2,10 @@ **Properties** -| Name | Type | Required | Description | -| :---- | :-------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| id\_ | str | ❌ | Unique identifier of the recipient | -| uid | str | ❌ | Unique identifier of the user associated with the recipient | -| name | str | ❌ | Name of the recipient | -| email | str | ❌ | Email of the recipient | -| role | TemplateRecipientRole | ❌ | Role of the recipient (SIGNER signs the document, RECEIVES_COPY receives a copy of the document, IN_PERSON_SIGNER signs the document in person, SENDER sends the document) | +| Name | Type | Required | Description | +| :---- | :------------------------------------------------ | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| id\_ | str | ❌ | Unique identifier of the recipient | +| uid | str | ❌ | Unique identifier of the user associated with the recipient | +| name | str | ❌ | Name of the recipient | +| email | str | ❌ | Email of the recipient | +| role | [TemplateRecipientRole](TemplateRecipientRole.md) | ❌ | Role of the recipient (SIGNER signs the document, RECEIVES_COPY receives a copy of the document, IN_PERSON_SIGNER signs the document in person, SENDER sends the document) | diff --git a/documentation/models/TemplateSigningStep.md b/documentation/models/TemplateSigningStep.md index 4b2e6ab..979ecf3 100644 --- a/documentation/models/TemplateSigningStep.md +++ b/documentation/models/TemplateSigningStep.md @@ -2,6 +2,6 @@ **Properties** -| Name | Type | Required | Description | -| :--------- | :---------------------- | :------- | :----------------- | -| recipients | List[TemplateRecipient] | ❌ | List of recipients | +| Name | Type | Required | Description | +| :--------- | :---------------------------------------------- | :------- | :----------------- | +| recipients | List[[TemplateRecipient](TemplateRecipient.md)] | ❌ | List of recipients | diff --git a/documentation/models/Webhook.md b/documentation/models/Webhook.md index 22fad1a..c8baf2e 100644 --- a/documentation/models/Webhook.md +++ b/documentation/models/Webhook.md @@ -2,8 +2,8 @@ **Properties** -| Name | Type | Required | Description | -| :----- | :----------- | :------- | :------------------------------- | -| id\_ | str | ❌ | Unique identifier of the webhook | -| event | WebhookEvent | ❌ | Event of the webhook | -| target | str | ❌ | Target URL of the webhook | +| Name | Type | Required | Description | +| :----- | :------------------------------ | :------- | :------------------------------- | +| id\_ | str | ❌ | Unique identifier of the webhook | +| event | [WebhookEvent](WebhookEvent.md) | ❌ | Event of the webhook | +| target | str | ❌ | Target URL of the webhook | diff --git a/documentation/services/SignplusService.md b/documentation/services/SignplusService.md index 04f91a1..d73ecb5 100644 --- a/documentation/services/SignplusService.md +++ b/documentation/services/SignplusService.md @@ -84,9 +84,9 @@ sdk = Signplus( request_body = CreateEnvelopeRequest( name="name", legality_level="SES", - expires_at=8, + expires_at=9, comment="comment", - sandbox=False + sandbox=True ) result = sdk.signplus.create_envelope(request_body=request_body) @@ -126,7 +126,7 @@ sdk = Signplus( request_body = CreateEnvelopeFromTemplateRequest( name="name", comment="comment", - sandbox=True + sandbox=False ) result = sdk.signplus.create_envelope_from_template( @@ -180,16 +180,16 @@ request_body = ListEnvelopesRequest( folder_ids=[ "folder_ids" ], - only_root_folder=True, - date_from=5, - date_to=9, + only_root_folder=False, + date_from=6, + date_to=6, uid="uid", - first=9, - last=7, + first=1, + last=9, after="after", before="before", order_field="CREATION_DATE", - ascending=True, + ascending=False, include_trash=True ) @@ -617,7 +617,7 @@ request_body = SetEnvelopeAttachmentsPlaceholdersRequest( "id_": "id", "name": "name", "hint": "hint", - "required": False, + "required": True, "multiple": True } ] @@ -878,7 +878,7 @@ sdk = Signplus( request_body = EnvelopeNotification( subject="subject", message="message", - reminder_interval=1 + reminder_interval=8 ) result = sdk.signplus.set_envelope_notification( @@ -919,7 +919,7 @@ sdk = Signplus( ) request_body = SetEnvelopeExpirationRequest( - expires_at=0 + expires_at=1 ) result = sdk.signplus.set_envelope_expiration_date( @@ -1071,11 +1071,11 @@ sdk = Signplus( request_body = AddAnnotationRequest( recipient_id="recipient_id", document_id="document_id", - page=2, - x=1.99, - y=8.2, - width=4.89, - height=9.43, + page=1, + x=6.91, + y=4.16, + width=9.91, + height=1.69, required=False, type_="TEXT", signature={ @@ -1085,8 +1085,8 @@ request_body = AddAnnotationRequest( "id_": "id" }, text={ - "size": 5.96, - "color": 8.73, + "size": 9.91, + "color": 9.84, "value": "value", "tooltip": "tooltip", "dynamic_field_name": "dynamic_field_name", @@ -1097,7 +1097,7 @@ request_body = AddAnnotationRequest( } }, datetime_={ - "size": 0.26, + "size": 1.1, "font": { "family": "UNKNOWN", "italic": True, @@ -1110,7 +1110,7 @@ request_body = AddAnnotationRequest( "format": "DMY_NUMERIC_SLASH" }, checkbox={ - "checked": True, + "checked": False, "style": "CIRCLE_CHECK" } ) @@ -1228,12 +1228,12 @@ request_body = ListTemplatesRequest( ids=[ "ids" ], - first=1, - last=6, + first=2, + last=5, after="after", before="before", order_field="TEMPLATE_ID", - ascending=False + ascending=True ) result = sdk.signplus.list_templates(request_body=request_body) @@ -1609,7 +1609,7 @@ sdk = Signplus( request_body = EnvelopeNotification( subject="subject", message="message", - reminder_interval=1 + reminder_interval=8 ) result = sdk.signplus.set_template_notification( @@ -1720,11 +1720,11 @@ sdk = Signplus( request_body = AddAnnotationRequest( recipient_id="recipient_id", document_id="document_id", - page=2, - x=1.99, - y=8.2, - width=4.89, - height=9.43, + page=1, + x=6.91, + y=4.16, + width=9.91, + height=1.69, required=False, type_="TEXT", signature={ @@ -1734,8 +1734,8 @@ request_body = AddAnnotationRequest( "id_": "id" }, text={ - "size": 5.96, - "color": 8.73, + "size": 9.91, + "color": 9.84, "value": "value", "tooltip": "tooltip", "dynamic_field_name": "dynamic_field_name", @@ -1746,7 +1746,7 @@ request_body = AddAnnotationRequest( } }, datetime_={ - "size": 0.26, + "size": 1.1, "font": { "family": "UNKNOWN", "italic": True, @@ -1759,7 +1759,7 @@ request_body = AddAnnotationRequest( "format": "DMY_NUMERIC_SLASH" }, checkbox={ - "checked": True, + "checked": False, "style": "CIRCLE_CHECK" } ) @@ -1883,7 +1883,7 @@ request_body = SetEnvelopeAttachmentsPlaceholdersRequest( "id_": "id", "name": "name", "hint": "hint", - "required": False, + "required": True, "multiple": True } ] diff --git a/documentation/snippets/snippets.json b/documentation/snippets/snippets.json new file mode 100644 index 0000000..9189844 --- /dev/null +++ b/documentation/snippets/snippets.json @@ -0,0 +1,282 @@ +{ + "endpoints": { + "/envelope": { + "post": "from signplus import Signplus\nfrom signplus.models import CreateEnvelopeRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = CreateEnvelopeRequest(\n name=\"name\",\n legality_level=\"SES\",\n expires_at=9,\n comment=\"comment\",\n sandbox=True\n)\n\nresult = sdk.signplus.create_envelope(request_body=request_body)\n\nprint(result)\n" + }, + "/envelope/from_template/{template_id}": { + "post": "from signplus import Signplus\nfrom signplus.models import CreateEnvelopeFromTemplateRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = CreateEnvelopeFromTemplateRequest(\n name=\"name\",\n comment=\"comment\",\n sandbox=False\n)\n\nresult = sdk.signplus.create_envelope_from_template(\n request_body=request_body,\n template_id=\"template_id\"\n)\n\nprint(result)\n" + }, + "/envelopes": { + "post": "from signplus import Signplus\nfrom signplus.models import ListEnvelopesRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = ListEnvelopesRequest(\n name=\"name\",\n tags=[\n \"tags\"\n ],\n comment=\"comment\",\n ids=[\n \"ids\"\n ],\n statuses=[\n \"DRAFT\"\n ],\n folder_ids=[\n \"folder_ids\"\n ],\n only_root_folder=False,\n date_from=6,\n date_to=6,\n uid=\"uid\",\n first=1,\n last=9,\n after=\"after\",\n before=\"before\",\n order_field=\"CREATION_DATE\",\n ascending=False,\n include_trash=True\n)\n\nresult = sdk.signplus.list_envelopes(request_body=request_body)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.get_envelope(envelope_id=\"envelope_id\")\n\nprint(result)\n", + "delete": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.delete_envelope(envelope_id=\"envelope_id\")\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/signed_documents": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.download_envelope_signed_documents(\n envelope_id=\"envelope_id\",\n certificate_of_completion=True\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/certificate": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.download_envelope_certificate(envelope_id=\"envelope_id\")\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/document/{document_id}": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.get_envelope_document(\n envelope_id=\"envelope_id\",\n document_id=\"document_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/documents": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.get_envelope_documents(envelope_id=\"envelope_id\")\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/document": { + "post": "from signplus import Signplus\nfrom signplus.models import AddEnvelopeDocumentRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = AddEnvelopeDocumentRequest(\n file=\"file\"\n)\n\nresult = sdk.signplus.add_envelope_document(\n request_body=request_body,\n envelope_id=\"envelope_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/dynamic_fields": { + "put": "from signplus import Signplus\nfrom signplus.models import SetEnvelopeDynamicFieldsRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = SetEnvelopeDynamicFieldsRequest(\n dynamic_fields=[\n {\n \"name\": \"name\",\n \"value\": \"value\"\n }\n ]\n)\n\nresult = sdk.signplus.set_envelope_dynamic_fields(\n request_body=request_body,\n envelope_id=\"envelope_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/signing_steps": { + "post": "from signplus import Signplus\nfrom signplus.models import AddEnvelopeSigningStepsRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = AddEnvelopeSigningStepsRequest(\n signing_steps=[\n {\n \"recipients\": [\n {\n \"id_\": \"id\",\n \"uid\": \"uid\",\n \"name\": \"name\",\n \"email\": \"email\",\n \"role\": \"SIGNER\",\n \"verification\": {\n \"type_\": \"SMS\",\n \"value\": \"value\"\n }\n }\n ]\n }\n ]\n)\n\nresult = sdk.signplus.add_envelope_signing_steps(\n request_body=request_body,\n envelope_id=\"envelope_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/attachments/settings": { + "put": "from signplus import Signplus\nfrom signplus.models import SetEnvelopeAttachmentsSettingsRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = SetEnvelopeAttachmentsSettingsRequest(\n settings={\n \"visible_to_recipients\": False\n }\n)\n\nresult = sdk.signplus.set_envelope_attachments_settings(\n request_body=request_body,\n envelope_id=\"envelope_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/attachments/placeholders": { + "put": "from signplus import Signplus\nfrom signplus.models import SetEnvelopeAttachmentsPlaceholdersRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = SetEnvelopeAttachmentsPlaceholdersRequest(\n placeholders=[\n {\n \"recipient_id\": \"recipient_id\",\n \"id_\": \"id\",\n \"name\": \"name\",\n \"hint\": \"hint\",\n \"required\": True,\n \"multiple\": True\n }\n ]\n)\n\nresult = sdk.signplus.set_envelope_attachments_placeholders(\n request_body=request_body,\n envelope_id=\"envelope_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/attachments/{file_id}": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.get_attachment_file(\n envelope_id=\"envelope_id\",\n file_id=\"file_id\"\n)\n\nwith open(\"output-file.ext\", \"wb\") as f:\n f.write(result)\n" + }, + "/envelope/{envelope_id}/send": { + "post": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.send_envelope(envelope_id=\"envelope_id\")\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/duplicate": { + "post": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.duplicate_envelope(envelope_id=\"envelope_id\")\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/void": { + "put": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.void_envelope(envelope_id=\"envelope_id\")\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/rename": { + "put": "from signplus import Signplus\nfrom signplus.models import RenameEnvelopeRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = RenameEnvelopeRequest(\n name=\"name\"\n)\n\nresult = sdk.signplus.rename_envelope(\n request_body=request_body,\n envelope_id=\"envelope_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/set_comment": { + "put": "from signplus import Signplus\nfrom signplus.models import SetEnvelopeCommentRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = SetEnvelopeCommentRequest(\n comment=\"comment\"\n)\n\nresult = sdk.signplus.set_envelope_comment(\n request_body=request_body,\n envelope_id=\"envelope_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/set_notification": { + "put": "from signplus import Signplus\nfrom signplus.models import EnvelopeNotification\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = EnvelopeNotification(\n subject=\"subject\",\n message=\"message\",\n reminder_interval=8\n)\n\nresult = sdk.signplus.set_envelope_notification(\n request_body=request_body,\n envelope_id=\"envelope_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/set_expiration_date": { + "put": "from signplus import Signplus\nfrom signplus.models import SetEnvelopeExpirationRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = SetEnvelopeExpirationRequest(\n expires_at=1\n)\n\nresult = sdk.signplus.set_envelope_expiration_date(\n request_body=request_body,\n envelope_id=\"envelope_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/set_legality_level": { + "put": "from signplus import Signplus\nfrom signplus.models import SetEnvelopeLegalityLevelRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = SetEnvelopeLegalityLevelRequest(\n legality_level=\"SES\"\n)\n\nresult = sdk.signplus.set_envelope_legality_level(\n request_body=request_body,\n envelope_id=\"envelope_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/annotations": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.get_envelope_annotations(envelope_id=\"envelope_id\")\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/annotations/{document_id}": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.get_envelope_document_annotations(\n envelope_id=\"envelope_id\",\n document_id=\"document_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/annotation": { + "post": "from signplus import Signplus\nfrom signplus.models import AddAnnotationRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = AddAnnotationRequest(\n recipient_id=\"recipient_id\",\n document_id=\"document_id\",\n page=1,\n x=6.91,\n y=4.16,\n width=9.91,\n height=1.69,\n required=False,\n type_=\"TEXT\",\n signature={\n \"id_\": \"id\"\n },\n initials={\n \"id_\": \"id\"\n },\n text={\n \"size\": 9.91,\n \"color\": 9.84,\n \"value\": \"value\",\n \"tooltip\": \"tooltip\",\n \"dynamic_field_name\": \"dynamic_field_name\",\n \"font\": {\n \"family\": \"UNKNOWN\",\n \"italic\": True,\n \"bold\": True\n }\n },\n datetime_={\n \"size\": 1.1,\n \"font\": {\n \"family\": \"UNKNOWN\",\n \"italic\": True,\n \"bold\": True\n },\n \"color\": \"color\",\n \"auto_fill\": True,\n \"timezone\": \"timezone\",\n \"timestamp\": 1,\n \"format\": \"DMY_NUMERIC_SLASH\"\n },\n checkbox={\n \"checked\": False,\n \"style\": \"CIRCLE_CHECK\"\n }\n)\n\nresult = sdk.signplus.add_envelope_annotation(\n request_body=request_body,\n envelope_id=\"envelope_id\"\n)\n\nprint(result)\n" + }, + "/envelope/{envelope_id}/annotation/{annotation_id}": { + "delete": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.delete_envelope_annotation(\n envelope_id=\"envelope_id\",\n annotation_id=\"annotation_id\"\n)\n\nprint(result)\n" + }, + "/template": { + "post": "from signplus import Signplus\nfrom signplus.models import CreateTemplateRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = CreateTemplateRequest(\n name=\"name\"\n)\n\nresult = sdk.signplus.create_template(request_body=request_body)\n\nprint(result)\n" + }, + "/templates": { + "post": "from signplus import Signplus\nfrom signplus.models import ListTemplatesRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = ListTemplatesRequest(\n name=\"name\",\n tags=[\n \"tags\"\n ],\n ids=[\n \"ids\"\n ],\n first=2,\n last=5,\n after=\"after\",\n before=\"before\",\n order_field=\"TEMPLATE_ID\",\n ascending=True\n)\n\nresult = sdk.signplus.list_templates(request_body=request_body)\n\nprint(result)\n" + }, + "/template/{template_id}": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.get_template(template_id=\"template_id\")\n\nprint(result)\n", + "delete": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.delete_template(template_id=\"template_id\")\n\nprint(result)\n" + }, + "/template/{template_id}/duplicate": { + "post": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.duplicate_template(template_id=\"template_id\")\n\nprint(result)\n" + }, + "/template/{template_id}/document": { + "post": "from signplus import Signplus\nfrom signplus.models import AddTemplateDocumentRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = AddTemplateDocumentRequest(\n file=\"file\"\n)\n\nresult = sdk.signplus.add_template_document(\n request_body=request_body,\n template_id=\"template_id\"\n)\n\nprint(result)\n" + }, + "/template/{template_id}/document/{document_id}": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.get_template_document(\n template_id=\"template_id\",\n document_id=\"document_id\"\n)\n\nprint(result)\n" + }, + "/template/{template_id}/documents": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.get_template_documents(template_id=\"template_id\")\n\nprint(result)\n" + }, + "/template/{template_id}/signing_steps": { + "post": "from signplus import Signplus\nfrom signplus.models import AddTemplateSigningStepsRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = AddTemplateSigningStepsRequest(\n signing_steps=[\n {\n \"recipients\": [\n {\n \"id_\": \"id\",\n \"uid\": \"uid\",\n \"name\": \"name\",\n \"email\": \"email\",\n \"role\": \"SIGNER\"\n }\n ]\n }\n ]\n)\n\nresult = sdk.signplus.add_template_signing_steps(\n request_body=request_body,\n template_id=\"template_id\"\n)\n\nprint(result)\n" + }, + "/template/{template_id}/rename": { + "put": "from signplus import Signplus\nfrom signplus.models import RenameTemplateRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = RenameTemplateRequest(\n name=\"name\"\n)\n\nresult = sdk.signplus.rename_template(\n request_body=request_body,\n template_id=\"template_id\"\n)\n\nprint(result)\n" + }, + "/template/{template_id}/set_comment": { + "put": "from signplus import Signplus\nfrom signplus.models import SetTemplateCommentRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = SetTemplateCommentRequest(\n comment=\"comment\"\n)\n\nresult = sdk.signplus.set_template_comment(\n request_body=request_body,\n template_id=\"template_id\"\n)\n\nprint(result)\n" + }, + "/template/{template_id}/set_notification": { + "put": "from signplus import Signplus\nfrom signplus.models import EnvelopeNotification\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = EnvelopeNotification(\n subject=\"subject\",\n message=\"message\",\n reminder_interval=8\n)\n\nresult = sdk.signplus.set_template_notification(\n request_body=request_body,\n template_id=\"template_id\"\n)\n\nprint(result)\n" + }, + "/template/{template_id}/annotations": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.get_template_annotations(template_id=\"template_id\")\n\nprint(result)\n" + }, + "/template/{template_id}/annotations/{document_id}": { + "get": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.get_document_template_annotations(\n template_id=\"template_id\",\n document_id=\"document_id\"\n)\n\nprint(result)\n" + }, + "/template/{template_id}/annotation": { + "post": "from signplus import Signplus\nfrom signplus.models import AddAnnotationRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = AddAnnotationRequest(\n recipient_id=\"recipient_id\",\n document_id=\"document_id\",\n page=1,\n x=6.91,\n y=4.16,\n width=9.91,\n height=1.69,\n required=False,\n type_=\"TEXT\",\n signature={\n \"id_\": \"id\"\n },\n initials={\n \"id_\": \"id\"\n },\n text={\n \"size\": 9.91,\n \"color\": 9.84,\n \"value\": \"value\",\n \"tooltip\": \"tooltip\",\n \"dynamic_field_name\": \"dynamic_field_name\",\n \"font\": {\n \"family\": \"UNKNOWN\",\n \"italic\": True,\n \"bold\": True\n }\n },\n datetime_={\n \"size\": 1.1,\n \"font\": {\n \"family\": \"UNKNOWN\",\n \"italic\": True,\n \"bold\": True\n },\n \"color\": \"color\",\n \"auto_fill\": True,\n \"timezone\": \"timezone\",\n \"timestamp\": 1,\n \"format\": \"DMY_NUMERIC_SLASH\"\n },\n checkbox={\n \"checked\": False,\n \"style\": \"CIRCLE_CHECK\"\n }\n)\n\nresult = sdk.signplus.add_template_annotation(\n request_body=request_body,\n template_id=\"template_id\"\n)\n\nprint(result)\n" + }, + "/template/{template_id}/annotation/{annotation_id}": { + "delete": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.delete_template_annotation(\n template_id=\"template_id\",\n annotation_id=\"annotation_id\"\n)\n\nprint(result)\n" + }, + "/template/{template_id}/attachments/settings": { + "put": "from signplus import Signplus\nfrom signplus.models import SetEnvelopeAttachmentsSettingsRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = SetEnvelopeAttachmentsSettingsRequest(\n settings={\n \"visible_to_recipients\": False\n }\n)\n\nresult = sdk.signplus.set_template_attachments_settings(\n request_body=request_body,\n template_id=\"template_id\"\n)\n\nprint(result)\n" + }, + "/template/{template_id}/attachments/placeholders": { + "put": "from signplus import Signplus\nfrom signplus.models import SetEnvelopeAttachmentsPlaceholdersRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = SetEnvelopeAttachmentsPlaceholdersRequest(\n placeholders=[\n {\n \"recipient_id\": \"recipient_id\",\n \"id_\": \"id\",\n \"name\": \"name\",\n \"hint\": \"hint\",\n \"required\": True,\n \"multiple\": True\n }\n ]\n)\n\nresult = sdk.signplus.set_template_attachments_placeholders(\n request_body=request_body,\n template_id=\"template_id\"\n)\n\nprint(result)\n" + }, + "/webhook": { + "post": "from signplus import Signplus\nfrom signplus.models import CreateWebhookRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = CreateWebhookRequest(\n event=\"ENVELOPE_EXPIRED\",\n target=\"target\"\n)\n\nresult = sdk.signplus.create_webhook(request_body=request_body)\n\nprint(result)\n" + }, + "/webhooks": { + "post": "from signplus import Signplus\nfrom signplus.models import ListWebhooksRequest\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nrequest_body = ListWebhooksRequest(\n webhook_id=\"webhook_id\",\n event=\"ENVELOPE_EXPIRED\"\n)\n\nresult = sdk.signplus.list_webhooks(request_body=request_body)\n\nprint(result)\n" + }, + "/webhook/{webhook_id}": { + "delete": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.delete_webhook(webhook_id=\"webhook_id\")\n\nprint(result)\n" + } + }, + "methodResponses": { + "/envelope": { + "post": "print(result)" + }, + "/envelope/from_template/{template_id}": { + "post": "print(result)" + }, + "/envelopes": { + "post": "print(result)" + }, + "/envelope/{envelope_id}": { + "get": "print(result)" + }, + "/envelope/{envelope_id}/signed_documents": { + "get": "print(result)" + }, + "/envelope/{envelope_id}/certificate": { + "get": "print(result)" + }, + "/envelope/{envelope_id}/document/{document_id}": { + "get": "print(result)" + }, + "/envelope/{envelope_id}/documents": { + "get": "print(result)" + }, + "/envelope/{envelope_id}/document": { + "post": "print(result)" + }, + "/envelope/{envelope_id}/dynamic_fields": { + "put": "print(result)" + }, + "/envelope/{envelope_id}/signing_steps": { + "post": "print(result)" + }, + "/envelope/{envelope_id}/attachments/settings": { + "put": "print(result)" + }, + "/envelope/{envelope_id}/attachments/placeholders": { + "put": "print(result)" + }, + "/envelope/{envelope_id}/attachments/{file_id}": { + "get": "with open(\"output-file.ext\", \"wb\") as f:\n f.write(result)" + }, + "/envelope/{envelope_id}/send": { + "post": "print(result)" + }, + "/envelope/{envelope_id}/duplicate": { + "post": "print(result)" + }, + "/envelope/{envelope_id}/void": { + "put": "print(result)" + }, + "/envelope/{envelope_id}/rename": { + "put": "print(result)" + }, + "/envelope/{envelope_id}/set_comment": { + "put": "print(result)" + }, + "/envelope/{envelope_id}/set_notification": { + "put": "print(result)" + }, + "/envelope/{envelope_id}/set_expiration_date": { + "put": "print(result)" + }, + "/envelope/{envelope_id}/set_legality_level": { + "put": "print(result)" + }, + "/envelope/{envelope_id}/annotations": { + "get": "print(result)" + }, + "/envelope/{envelope_id}/annotations/{document_id}": { + "get": "print(result)" + }, + "/envelope/{envelope_id}/annotation": { + "post": "print(result)" + }, + "/template": { + "post": "print(result)" + }, + "/templates": { + "post": "print(result)" + }, + "/template/{template_id}": { + "get": "print(result)" + }, + "/template/{template_id}/duplicate": { + "post": "print(result)" + }, + "/template/{template_id}/document": { + "post": "print(result)" + }, + "/template/{template_id}/document/{document_id}": { + "get": "print(result)" + }, + "/template/{template_id}/documents": { + "get": "print(result)" + }, + "/template/{template_id}/signing_steps": { + "post": "print(result)" + }, + "/template/{template_id}/rename": { + "put": "print(result)" + }, + "/template/{template_id}/set_comment": { + "put": "print(result)" + }, + "/template/{template_id}/set_notification": { + "put": "print(result)" + }, + "/template/{template_id}/annotations": { + "get": "print(result)" + }, + "/template/{template_id}/annotations/{document_id}": { + "get": "print(result)" + }, + "/template/{template_id}/annotation": { + "post": "print(result)" + }, + "/template/{template_id}/attachments/settings": { + "put": "print(result)" + }, + "/template/{template_id}/attachments/placeholders": { + "put": "print(result)" + }, + "/webhook": { + "post": "print(result)" + }, + "/webhooks": { + "post": "print(result)" + } + }, + "example": "from signplus import Signplus\n\nsdk = Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)\n\nresult = sdk.signplus.get_envelope(envelope_id=\"envelope_id\")\n\nprint(result)\n", + "authentication": { + "bearer": { + "constructor": "Signplus(\n access_token=\"YOUR_ACCESS_TOKEN\",\n timeout=10000\n)", + "setter": "sdk.set_access_token(\"YOUR_ACCESS_TOKEN\")" + } + } +} diff --git a/examples/install.cmd b/examples/install.cmd index 127b161..68d9fbc 100644 --- a/examples/install.cmd +++ b/examples/install.cmd @@ -2,4 +2,4 @@ python -m venv .venv call .venv\Scripts\activate pip install build python -m build --outdir dist ..\ -pip install dist\signplus_python-1.4.0-py3-none-any.whl --force-reinstall +pip install dist\signplus_python-3.1.0-py3-none-any.whl --force-reinstall diff --git a/examples/install.sh b/examples/install.sh index 83ac5a0..14f18eb 100644 --- a/examples/install.sh +++ b/examples/install.sh @@ -1,5 +1,16 @@ -python -m venv .venv +#!/bin/bash + +if command -v python3 &> /dev/null; then + PYTHON_CMD=python3 +elif command -v python &> /dev/null && python --version 2>&1 | grep -qE "Python 3\."; then + PYTHON_CMD=python +else + echo "Error: Python 3 is not installed or not found in PATH" + exit 1 +fi + +$PYTHON_CMD -m venv .venv . .venv/bin/activate -pip install build -python -m build --outdir dist ../ -pip install dist/signplus_python-1.4.0-py3-none-any.whl --force-reinstall +$PYTHON_CMD -m pip install build +$PYTHON_CMD -m build --outdir dist ../ +$PYTHON_CMD -m pip install dist/signplus_python-3.1.0-py3-none-any.whl --force-reinstall diff --git a/install.cmd b/install.cmd index 618b60f..ef80ac2 100644 --- a/install.cmd +++ b/install.cmd @@ -15,7 +15,7 @@ if "%USE_VENV%"=="1" ( pip install build python -m build --outdir dist . -pip install dist\signplus_python-1.4.0-py3-none-any.whl --force-reinstall +pip install dist\signplus_python-3.1.0-py3-none-any.whl --force-reinstall if "%USE_VENV%"=="1" ( deactivate diff --git a/install.sh b/install.sh index f7e99b9..2206c2d 100644 --- a/install.sh +++ b/install.sh @@ -1,5 +1,14 @@ #!/bin/bash +if command -v python3 &> /dev/null; then + PYTHON_CMD=python3 +elif command -v python &> /dev/null && python --version 2>&1 | grep -qE "Python 3\."; then + PYTHON_CMD=python +else + echo "Error: Python 3 is not installed or not found in PATH" + exit 1 +fi + USE_VENV=0 for arg in "$@" @@ -13,13 +22,13 @@ do done if [ "$USE_VENV" -eq 1 ]; then - python -m venv .venv + $PYTHON_CMD -m venv .venv . .venv/bin/activate fi -pip install build -python -m build --outdir dist . -pip install dist/signplus_python-1.4.0-py3-none-any.whl --force-reinstall +$PYTHON_CMD -m pip install build +$PYTHON_CMD -m build --outdir dist . +$PYTHON_CMD -m pip install dist/signplus_python-3.1.0-py3-none-any.whl --force-reinstall if [ "$USE_VENV" -eq 1 ]; then deactivate diff --git a/prettier.config.js b/prettier.config.js new file mode 100644 index 0000000..f68d86e --- /dev/null +++ b/prettier.config.js @@ -0,0 +1,41 @@ +// Prettier configuration for code-formatter lambda +// Aligned with sdk-gen/prettier.config.ts + +module.exports = { + printWidth: 100, + tabWidth: 2, + useTabs: false, + semi: true, + singleQuote: true, + quoteProps: 'as-needed', + jsxSingleQuote: false, + trailingComma: 'all', + bracketSpacing: true, + arrowParens: 'always', + overrides: [ + { + files: '.editorconfig', + options: { parser: 'yaml' }, + }, + { + files: 'LICENSE', + options: { parser: 'markdown' }, + }, + { + files: '*.php', + options: { + parser: 'php', + phpVersion: '8.0', + trailingCommaPHP: false, + }, + }, + { + files: '*.md', + options: { + parser: 'markdown', + phpVersion: '8.0', + trailingCommaPHP: false, + }, + }, + ], +}; diff --git a/pyproject.toml b/pyproject.toml index b9e80d2..31d7865 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,11 +4,20 @@ build-backend = "setuptools.build_meta" [project] name = "signplus-python" -version = "1.4.0" +version = "3.1.0" license = { text = "MIT" } description = """Integrate legally-binding electronic signature to your workflow""" readme = "PyPI_README.md" requires-python = ">=3.9" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: MIT License", + "Topic :: Software Development" +] dependencies = [ - "requests>=2.31.0" + "requests>=2.31.0", + "pydantic>=2.0.0,<3.0.0" ] + +[project.urls] +Repository = "https://github.com/alohihq/signplus-python" diff --git a/src/signplus/models/__init__.py b/src/signplus/models/__init__.py index 87b0beb..fca9ca2 100644 --- a/src/signplus/models/__init__.py +++ b/src/signplus/models/__init__.py @@ -1,75 +1,198 @@ -from .create_envelope_request import CreateEnvelopeRequest -from .envelope import Envelope -from .create_envelope_from_template_request import CreateEnvelopeFromTemplateRequest -from .list_envelopes_request import ListEnvelopesRequest -from .list_envelopes_response import ListEnvelopesResponse -from .document import Document -from .list_envelope_documents_response import ListEnvelopeDocumentsResponse -from .add_envelope_document_request import AddEnvelopeDocumentRequest -from .set_envelope_dynamic_fields_request import SetEnvelopeDynamicFieldsRequest -from .add_envelope_signing_steps_request import AddEnvelopeSigningStepsRequest -from .set_envelope_attachments_settings_request import ( - SetEnvelopeAttachmentsSettingsRequest, +"""Lazy model exports. + +Names are resolved on first attribute access via PEP 562 ``__getattr__``, +then cached in module globals. Avoids the multi-second eager-import cost +on SDKs with thousands of generated models. +""" + +import importlib + +_MODEL_TO_MODULE = { + "CreateEnvelopeRequest": "create_envelope_request", + "Envelope": "envelope", + "CreateEnvelopeFromTemplateRequest": "create_envelope_from_template_request", + "ListEnvelopesRequest": "list_envelopes_request", + "ListEnvelopesResponse": "list_envelopes_response", + "Document": "document", + "ListEnvelopeDocumentsResponse": "list_envelope_documents_response", + "AddEnvelopeDocumentRequest": "add_envelope_document_request", + "SetEnvelopeDynamicFieldsRequest": "set_envelope_dynamic_fields_request", + "AddEnvelopeSigningStepsRequest": "add_envelope_signing_steps_request", + "SetEnvelopeAttachmentsSettingsRequest": "set_envelope_attachments_settings_request", + "EnvelopeAttachments": "envelope_attachments", + "SetEnvelopeAttachmentsPlaceholdersRequest": "set_envelope_attachments_placeholders_request", + "RenameEnvelopeRequest": "rename_envelope_request", + "SetEnvelopeCommentRequest": "set_envelope_comment_request", + "EnvelopeNotification": "envelope_notification", + "SetEnvelopeExpirationRequest": "set_envelope_expiration_request", + "SetEnvelopeLegalityLevelRequest": "set_envelope_legality_level_request", + "Annotation": "annotation", + "ListEnvelopeDocumentAnnotationsResponse": "list_envelope_document_annotations_response", + "AddAnnotationRequest": "add_annotation_request", + "CreateTemplateRequest": "create_template_request", + "Template": "template", + "ListTemplatesRequest": "list_templates_request", + "ListTemplatesResponse": "list_templates_response", + "AddTemplateDocumentRequest": "add_template_document_request", + "ListTemplateDocumentsResponse": "list_template_documents_response", + "AddTemplateSigningStepsRequest": "add_template_signing_steps_request", + "RenameTemplateRequest": "rename_template_request", + "SetTemplateCommentRequest": "set_template_comment_request", + "ListTemplateAnnotationsResponse": "list_template_annotations_response", + "ListTemplateDocumentAnnotationsResponse": "list_template_document_annotations_response", + "CreateWebhookRequest": "create_webhook_request", + "Webhook": "webhook", + "ListWebhooksRequest": "list_webhooks_request", + "ListWebhooksResponse": "list_webhooks_response", + "EnvelopeLegalityLevel": "envelope_legality_level", + "EnvelopeFlowType": "envelope_flow_type", + "EnvelopeStatus": "envelope_status", + "SigningStep": "signing_step", + "Recipient": "recipient", + "RecipientRole": "recipient_role", + "RecipientVerification": "recipient_verification", + "RecipientVerificationType": "recipient_verification_type", + "Page": "page", + "AttachmentSettings": "attachment_settings", + "AttachmentPlaceholdersPerRecipient": "attachment_placeholders_per_recipient", + "AttachmentPlaceholder": "attachment_placeholder", + "AttachmentPlaceholderFile": "attachment_placeholder_file", + "EnvelopeOrderField": "envelope_order_field", + "DynamicField": "dynamic_field", + "AttachmentPlaceholderRequest": "attachment_placeholder_request", + "AnnotationType": "annotation_type", + "AnnotationSignature": "annotation_signature", + "AnnotationInitials": "annotation_initials", + "AnnotationText": "annotation_text", + "AnnotationDateTime": "annotation_date_time", + "AnnotationCheckbox": "annotation_checkbox", + "AnnotationFont": "annotation_font", + "AnnotationFontFamily": "annotation_font_family", + "AnnotationDateTimeFormat": "annotation_date_time_format", + "AnnotationCheckboxStyle": "annotation_checkbox_style", + "TemplateSigningStep": "template_signing_step", + "TemplateRecipient": "template_recipient", + "TemplateRecipientRole": "template_recipient_role", + "TemplateOrderField": "template_order_field", + "WebhookEvent": "webhook_event", +} + +_REBUILD_NAMES = frozenset( + { + "CreateEnvelopeRequest", + "Envelope", + "CreateEnvelopeFromTemplateRequest", + "ListEnvelopesRequest", + "ListEnvelopesResponse", + "Document", + "ListEnvelopeDocumentsResponse", + "AddEnvelopeDocumentRequest", + "SetEnvelopeDynamicFieldsRequest", + "AddEnvelopeSigningStepsRequest", + "SetEnvelopeAttachmentsSettingsRequest", + "EnvelopeAttachments", + "SetEnvelopeAttachmentsPlaceholdersRequest", + "RenameEnvelopeRequest", + "SetEnvelopeCommentRequest", + "EnvelopeNotification", + "SetEnvelopeExpirationRequest", + "SetEnvelopeLegalityLevelRequest", + "Annotation", + "ListEnvelopeDocumentAnnotationsResponse", + "AddAnnotationRequest", + "CreateTemplateRequest", + "Template", + "ListTemplatesRequest", + "ListTemplatesResponse", + "AddTemplateDocumentRequest", + "ListTemplateDocumentsResponse", + "AddTemplateSigningStepsRequest", + "RenameTemplateRequest", + "SetTemplateCommentRequest", + "ListTemplateAnnotationsResponse", + "ListTemplateDocumentAnnotationsResponse", + "CreateWebhookRequest", + "Webhook", + "ListWebhooksRequest", + "ListWebhooksResponse", + "SigningStep", + "Recipient", + "RecipientVerification", + "Page", + "AttachmentSettings", + "AttachmentPlaceholdersPerRecipient", + "AttachmentPlaceholder", + "AttachmentPlaceholderFile", + "DynamicField", + "AttachmentPlaceholderRequest", + "AnnotationSignature", + "AnnotationInitials", + "AnnotationText", + "AnnotationDateTime", + "AnnotationCheckbox", + "AnnotationFont", + "TemplateSigningStep", + "TemplateRecipient", + } ) -from .envelope_attachments import EnvelopeAttachments -from .set_envelope_attachments_placeholders_request import ( - SetEnvelopeAttachmentsPlaceholdersRequest, -) -from .rename_envelope_request import RenameEnvelopeRequest -from .set_envelope_comment_request import SetEnvelopeCommentRequest -from .envelope_notification import EnvelopeNotification -from .set_envelope_expiration_request import SetEnvelopeExpirationRequest -from .set_envelope_legality_level_request import SetEnvelopeLegalityLevelRequest -from .annotation import Annotation -from .list_envelope_document_annotations_response import ( - ListEnvelopeDocumentAnnotationsResponse, -) -from .add_annotation_request import AddAnnotationRequest -from .create_template_request import CreateTemplateRequest -from .template import Template -from .list_templates_request import ListTemplatesRequest -from .list_templates_response import ListTemplatesResponse -from .add_template_document_request import AddTemplateDocumentRequest -from .list_template_documents_response import ListTemplateDocumentsResponse -from .add_template_signing_steps_request import AddTemplateSigningStepsRequest -from .rename_template_request import RenameTemplateRequest -from .set_template_comment_request import SetTemplateCommentRequest -from .list_template_annotations_response import ListTemplateAnnotationsResponse -from .list_template_document_annotations_response import ( - ListTemplateDocumentAnnotationsResponse, -) -from .create_webhook_request import CreateWebhookRequest -from .webhook import Webhook -from .list_webhooks_request import ListWebhooksRequest -from .list_webhooks_response import ListWebhooksResponse -from .envelope_legality_level import EnvelopeLegalityLevel -from .envelope_flow_type import EnvelopeFlowType -from .envelope_status import EnvelopeStatus -from .signing_step import SigningStep -from .recipient import Recipient -from .recipient_role import RecipientRole -from .recipient_verification import RecipientVerification -from .recipient_verification_type import RecipientVerificationType -from .page import Page -from .attachment_settings import AttachmentSettings -from .attachment_placeholders_per_recipient import AttachmentPlaceholdersPerRecipient -from .attachment_placeholder import AttachmentPlaceholder -from .attachment_placeholder_file import AttachmentPlaceholderFile -from .envelope_order_field import EnvelopeOrderField -from .dynamic_field import DynamicField -from .attachment_placeholder_request import AttachmentPlaceholderRequest -from .annotation_type import AnnotationType -from .annotation_signature import AnnotationSignature -from .annotation_initials import AnnotationInitials -from .annotation_text import AnnotationText -from .annotation_date_time import AnnotationDateTime -from .annotation_checkbox import AnnotationCheckbox -from .annotation_font import AnnotationFont -from .annotation_font_family import AnnotationFontFamily -from .annotation_date_time_format import AnnotationDateTimeFormat -from .annotation_checkbox_style import AnnotationCheckboxStyle -from .template_signing_step import TemplateSigningStep -from .template_recipient import TemplateRecipient -from .template_recipient_role import TemplateRecipientRole -from .template_order_field import TemplateOrderField -from .webhook_event import WebhookEvent + +__all__ = list(_MODEL_TO_MODULE.keys()) + +_rebuilt = False + + +def _load(name): + module = _MODEL_TO_MODULE.get(name) + if module is None: + return None + obj = getattr(importlib.import_module("." + module, __name__), name) + globals()[name] = obj + return obj + + +def _ensure_rebuilt(): + """Resolve forward refs across every BaseModel in one batched pass. + + Individual model files import their cross-references inside a + ``TYPE_CHECKING`` block, so at runtime each file's globals contain + only itself. ``model_rebuild()`` walks the call stack to find + forward-ref names — calling it from this module once every + BaseModel has been loaded into our globals is what lets pydantic + resolve circular refs (the same shape the prior eager-import form + relied on). Enums, Union types, and error models stay lazy. + """ + global _rebuilt + if _rebuilt: + return + _rebuilt = True + for name in _REBUILD_NAMES: + if name not in globals(): + try: + _load(name) + except Exception: + pass + ns = globals() + for name in _REBUILD_NAMES: + cls = ns.get(name) + if cls is None: + continue + try: + # _types_namespace is mandatory: pydantic resolves forward refs + # against caller-frame locals by default, but we're calling from + # inside a helper — the names live in this module's globals. + cls.model_rebuild(_types_namespace=ns) + except Exception: + pass + + +def __getattr__(name): + if name not in _MODEL_TO_MODULE: + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + obj = _load(name) + if name in _REBUILD_NAMES: + _ensure_rebuilt() + return obj + + +def __dir__(): + return sorted(set(globals()).union(_MODEL_TO_MODULE)) diff --git a/src/signplus/models/add_annotation_request.py b/src/signplus/models/add_annotation_request.py index 2a6c4c8..30ca07f 100644 --- a/src/signplus/models/add_annotation_request.py +++ b/src/signplus/models/add_annotation_request.py @@ -1,7 +1,7 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .annotation_type import AnnotationType from .annotation_signature import AnnotationSignature from .annotation_initials import AnnotationInitials @@ -10,7 +10,6 @@ from .annotation_checkbox import AnnotationCheckbox -@JsonMap({"type_": "type", "datetime_": "datetime"}) class AddAnnotationRequest(BaseModel): """AddAnnotationRequest @@ -44,74 +43,43 @@ class AddAnnotationRequest(BaseModel): :type checkbox: AnnotationCheckbox, optional """ - def __init__( - self, - document_id: str, - page: int, - x: float, - y: float, - width: float, - height: float, - type_: AnnotationType, - recipient_id: str = SENTINEL, - required: bool = SENTINEL, - signature: AnnotationSignature = SENTINEL, - initials: AnnotationInitials = SENTINEL, - text: AnnotationText = SENTINEL, - datetime_: AnnotationDateTime = SENTINEL, - checkbox: AnnotationCheckbox = SENTINEL, - **kwargs, - ): - """AddAnnotationRequest - - :param recipient_id: ID of the recipient, defaults to None - :type recipient_id: str, optional - :param document_id: ID of the document - :type document_id: str - :param page: Page number where the annotation is placed - :type page: int - :param x: X coordinate of the annotation (in % of the page width from 0 to 100) from the top left corner - :type x: float - :param y: Y coordinate of the annotation (in % of the page height from 0 to 100) from the top left corner - :type y: float - :param width: Width of the annotation (in % of the page width from 0 to 100) - :type width: float - :param height: Height of the annotation (in % of the page height from 0 to 100) - :type height: float - :param required: required, defaults to None - :type required: bool, optional - :param type_: Type of the annotation - :type type_: AnnotationType - :param signature: Signature annotation (null if annotation is not a signature), defaults to None - :type signature: AnnotationSignature, optional - :param initials: Initials annotation (null if annotation is not initials), defaults to None - :type initials: AnnotationInitials, optional - :param text: Text annotation (null if annotation is not a text), defaults to None - :type text: AnnotationText, optional - :param datetime_: Date annotation (null if annotation is not a date), defaults to None - :type datetime_: AnnotationDateTime, optional - :param checkbox: Checkbox annotation (null if annotation is not a checkbox), defaults to None - :type checkbox: AnnotationCheckbox, optional - """ - if recipient_id is not SENTINEL: - self.recipient_id = recipient_id - self.document_id = document_id - self.page = page - self.x = x - self.y = y - self.width = width - self.height = height - if required is not SENTINEL: - self.required = required - self.type_ = self._enum_matching(type_, AnnotationType.list(), "type_") - if signature is not SENTINEL: - self.signature = self._define_object(signature, AnnotationSignature) - if initials is not SENTINEL: - self.initials = self._define_object(initials, AnnotationInitials) - if text is not SENTINEL: - self.text = self._define_object(text, AnnotationText) - if datetime_ is not SENTINEL: - self.datetime_ = self._define_object(datetime_, AnnotationDateTime) - if checkbox is not SENTINEL: - self.checkbox = self._define_object(checkbox, AnnotationCheckbox) - self._kwargs = kwargs + recipient_id: Optional[str] = Field(default=None, description="ID of the recipient") + document_id: str = Field(description="ID of the document") + page: int = Field(description="Page number where the annotation is placed") + x: float = Field( + description="X coordinate of the annotation (in % of the page width from 0 to 100) from the top left corner" + ) + y: float = Field( + description="Y coordinate of the annotation (in % of the page height from 0 to 100) from the top left corner" + ) + width: float = Field( + description="Width of the annotation (in % of the page width from 0 to 100)" + ) + height: float = Field( + description="Height of the annotation (in % of the page height from 0 to 100)" + ) + required: Optional[bool] = Field(default=None) + type_: AnnotationType = Field( + alias="type", serialization_alias="type", description="Type of the annotation" + ) + signature: Optional[AnnotationSignature] = Field( + default=None, + description="Signature annotation (null if annotation is not a signature)", + ) + initials: Optional[AnnotationInitials] = Field( + default=None, + description="Initials annotation (null if annotation is not initials)", + ) + text: Optional[AnnotationText] = Field( + default=None, description="Text annotation (null if annotation is not a text)" + ) + datetime_: Optional[AnnotationDateTime] = Field( + alias="datetime", + serialization_alias="datetime", + default=None, + description="Date annotation (null if annotation is not a date)", + ) + checkbox: Optional[AnnotationCheckbox] = Field( + default=None, + description="Checkbox annotation (null if annotation is not a checkbox)", + ) diff --git a/src/signplus/models/add_envelope_document_request.py b/src/signplus/models/add_envelope_document_request.py index 90962a7..11a584e 100644 --- a/src/signplus/models/add_envelope_document_request.py +++ b/src/signplus/models/add_envelope_document_request.py @@ -1,9 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL -@JsonMap({}) class AddEnvelopeDocumentRequest(BaseModel): """AddEnvelopeDocumentRequest @@ -11,12 +10,6 @@ class AddEnvelopeDocumentRequest(BaseModel): :type file: bytes, optional """ - def __init__(self, file: bytes = SENTINEL, **kwargs): - """AddEnvelopeDocumentRequest - - :param file: File to upload in binary format, defaults to None - :type file: bytes, optional - """ - if file is not SENTINEL: - self.file = file - self._kwargs = kwargs + file: Optional[bytes] = Field( + default=None, description="File to upload in binary format" + ) diff --git a/src/signplus/models/add_envelope_signing_steps_request.py b/src/signplus/models/add_envelope_signing_steps_request.py index e5641f9..a91407c 100644 --- a/src/signplus/models/add_envelope_signing_steps_request.py +++ b/src/signplus/models/add_envelope_signing_steps_request.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .signing_step import SigningStep -@JsonMap({}) class AddEnvelopeSigningStepsRequest(BaseModel): """AddEnvelopeSigningStepsRequest @@ -14,12 +13,6 @@ class AddEnvelopeSigningStepsRequest(BaseModel): :type signing_steps: List[SigningStep], optional """ - def __init__(self, signing_steps: List[SigningStep] = SENTINEL, **kwargs): - """AddEnvelopeSigningStepsRequest - - :param signing_steps: List of signing steps, defaults to None - :type signing_steps: List[SigningStep], optional - """ - if signing_steps is not SENTINEL: - self.signing_steps = self._define_list(signing_steps, SigningStep) - self._kwargs = kwargs + signing_steps: Optional[List[SigningStep]] = Field( + default=None, description="List of signing steps" + ) diff --git a/src/signplus/models/add_template_document_request.py b/src/signplus/models/add_template_document_request.py index 2210283..45b3f0e 100644 --- a/src/signplus/models/add_template_document_request.py +++ b/src/signplus/models/add_template_document_request.py @@ -1,8 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -@JsonMap({}) class AddTemplateDocumentRequest(BaseModel): """AddTemplateDocumentRequest @@ -10,11 +10,4 @@ class AddTemplateDocumentRequest(BaseModel): :type file: bytes """ - def __init__(self, file: bytes, **kwargs): - """AddTemplateDocumentRequest - - :param file: File to upload in binary format - :type file: bytes - """ - self.file = file - self._kwargs = kwargs + file: bytes = Field(description="File to upload in binary format") diff --git a/src/signplus/models/add_template_signing_steps_request.py b/src/signplus/models/add_template_signing_steps_request.py index 6a87d7e..5c48d18 100644 --- a/src/signplus/models/add_template_signing_steps_request.py +++ b/src/signplus/models/add_template_signing_steps_request.py @@ -1,11 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel from .template_signing_step import TemplateSigningStep -@JsonMap({}) class AddTemplateSigningStepsRequest(BaseModel): """AddTemplateSigningStepsRequest @@ -13,11 +13,6 @@ class AddTemplateSigningStepsRequest(BaseModel): :type signing_steps: List[TemplateSigningStep] """ - def __init__(self, signing_steps: List[TemplateSigningStep], **kwargs): - """AddTemplateSigningStepsRequest - - :param signing_steps: List of signing steps - :type signing_steps: List[TemplateSigningStep] - """ - self.signing_steps = self._define_list(signing_steps, TemplateSigningStep) - self._kwargs = kwargs + signing_steps: List[TemplateSigningStep] = Field( + description="List of signing steps" + ) diff --git a/src/signplus/models/annotation.py b/src/signplus/models/annotation.py index 28efc86..48096ab 100644 --- a/src/signplus/models/annotation.py +++ b/src/signplus/models/annotation.py @@ -1,7 +1,7 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .annotation_type import AnnotationType from .annotation_signature import AnnotationSignature from .annotation_initials import AnnotationInitials @@ -10,7 +10,6 @@ from .annotation_checkbox import AnnotationCheckbox -@JsonMap({"id_": "id", "type_": "type", "datetime_": "datetime"}) class Annotation(BaseModel): """Annotation @@ -46,86 +45,60 @@ class Annotation(BaseModel): :type checkbox: AnnotationCheckbox, optional """ - def __init__( - self, - id_: str = SENTINEL, - recipient_id: str = SENTINEL, - document_id: str = SENTINEL, - page: int = SENTINEL, - x: float = SENTINEL, - y: float = SENTINEL, - width: float = SENTINEL, - height: float = SENTINEL, - required: bool = SENTINEL, - type_: AnnotationType = SENTINEL, - signature: AnnotationSignature = SENTINEL, - initials: AnnotationInitials = SENTINEL, - text: AnnotationText = SENTINEL, - datetime_: AnnotationDateTime = SENTINEL, - checkbox: AnnotationCheckbox = SENTINEL, - **kwargs, - ): - """Annotation - - :param id_: Unique identifier of the annotation, defaults to None - :type id_: str, optional - :param recipient_id: ID of the recipient, defaults to None - :type recipient_id: str, optional - :param document_id: ID of the document, defaults to None - :type document_id: str, optional - :param page: Page number where the annotation is placed, defaults to None - :type page: int, optional - :param x: X coordinate of the annotation (in % of the page width from 0 to 100) from the top left corner, defaults to None - :type x: float, optional - :param y: Y coordinate of the annotation (in % of the page height from 0 to 100) from the top left corner, defaults to None - :type y: float, optional - :param width: Width of the annotation (in % of the page width from 0 to 100), defaults to None - :type width: float, optional - :param height: Height of the annotation (in % of the page height from 0 to 100), defaults to None - :type height: float, optional - :param required: Whether the annotation is required, defaults to None - :type required: bool, optional - :param type_: Type of the annotation, defaults to None - :type type_: AnnotationType, optional - :param signature: Signature annotation (null if annotation is not a signature), defaults to None - :type signature: AnnotationSignature, optional - :param initials: Initials annotation (null if annotation is not initials), defaults to None - :type initials: AnnotationInitials, optional - :param text: Text annotation (null if annotation is not a text), defaults to None - :type text: AnnotationText, optional - :param datetime_: Date annotation (null if annotation is not a date), defaults to None - :type datetime_: AnnotationDateTime, optional - :param checkbox: Checkbox annotation (null if annotation is not a checkbox), defaults to None - :type checkbox: AnnotationCheckbox, optional - """ - if id_ is not SENTINEL: - self.id_ = id_ - if recipient_id is not SENTINEL: - self.recipient_id = recipient_id - if document_id is not SENTINEL: - self.document_id = document_id - if page is not SENTINEL: - self.page = page - if x is not SENTINEL: - self.x = x - if y is not SENTINEL: - self.y = y - if width is not SENTINEL: - self.width = width - if height is not SENTINEL: - self.height = height - if required is not SENTINEL: - self.required = required - if type_ is not SENTINEL: - self.type_ = self._enum_matching(type_, AnnotationType.list(), "type_") - if signature is not SENTINEL: - self.signature = self._define_object(signature, AnnotationSignature) - if initials is not SENTINEL: - self.initials = self._define_object(initials, AnnotationInitials) - if text is not SENTINEL: - self.text = self._define_object(text, AnnotationText) - if datetime_ is not SENTINEL: - self.datetime_ = self._define_object(datetime_, AnnotationDateTime) - if checkbox is not SENTINEL: - self.checkbox = self._define_object(checkbox, AnnotationCheckbox) - self._kwargs = kwargs + id_: Optional[str] = Field( + alias="id", + serialization_alias="id", + default=None, + description="Unique identifier of the annotation", + ) + recipient_id: Optional[str] = Field(default=None, description="ID of the recipient") + document_id: Optional[str] = Field(default=None, description="ID of the document") + page: Optional[int] = Field( + default=None, description="Page number where the annotation is placed" + ) + x: Optional[float] = Field( + default=None, + description="X coordinate of the annotation (in % of the page width from 0 to 100) from the top left corner", + ) + y: Optional[float] = Field( + default=None, + description="Y coordinate of the annotation (in % of the page height from 0 to 100) from the top left corner", + ) + width: Optional[float] = Field( + default=None, + description="Width of the annotation (in % of the page width from 0 to 100)", + ) + height: Optional[float] = Field( + default=None, + description="Height of the annotation (in % of the page height from 0 to 100)", + ) + required: Optional[bool] = Field( + default=None, description="Whether the annotation is required" + ) + type_: Optional[AnnotationType] = Field( + alias="type", + serialization_alias="type", + default=None, + description="Type of the annotation", + ) + signature: Optional[AnnotationSignature] = Field( + default=None, + description="Signature annotation (null if annotation is not a signature)", + ) + initials: Optional[AnnotationInitials] = Field( + default=None, + description="Initials annotation (null if annotation is not initials)", + ) + text: Optional[AnnotationText] = Field( + default=None, description="Text annotation (null if annotation is not a text)" + ) + datetime_: Optional[AnnotationDateTime] = Field( + alias="datetime", + serialization_alias="datetime", + default=None, + description="Date annotation (null if annotation is not a date)", + ) + checkbox: Optional[AnnotationCheckbox] = Field( + default=None, + description="Checkbox annotation (null if annotation is not a checkbox)", + ) diff --git a/src/signplus/models/annotation_checkbox.py b/src/signplus/models/annotation_checkbox.py index 65a797b..95bc634 100644 --- a/src/signplus/models/annotation_checkbox.py +++ b/src/signplus/models/annotation_checkbox.py @@ -1,11 +1,10 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .annotation_checkbox_style import AnnotationCheckboxStyle -@JsonMap({}) class AnnotationCheckbox(BaseModel): """Checkbox annotation (null if annotation is not a checkbox) @@ -15,23 +14,9 @@ class AnnotationCheckbox(BaseModel): :type style: AnnotationCheckboxStyle, optional """ - def __init__( - self, - checked: bool = SENTINEL, - style: AnnotationCheckboxStyle = SENTINEL, - **kwargs, - ): - """Checkbox annotation (null if annotation is not a checkbox) - - :param checked: Whether the checkbox is checked, defaults to None - :type checked: bool, optional - :param style: Style of the checkbox, defaults to None - :type style: AnnotationCheckboxStyle, optional - """ - if checked is not SENTINEL: - self.checked = checked - if style is not SENTINEL: - self.style = self._enum_matching( - style, AnnotationCheckboxStyle.list(), "style" - ) - self._kwargs = kwargs + checked: Optional[bool] = Field( + default=None, description="Whether the checkbox is checked" + ) + style: Optional[AnnotationCheckboxStyle] = Field( + default=None, description="Style of the checkbox" + ) diff --git a/src/signplus/models/annotation_checkbox_style.py b/src/signplus/models/annotation_checkbox_style.py index d8e388b..74bc967 100644 --- a/src/signplus/models/annotation_checkbox_style.py +++ b/src/signplus/models/annotation_checkbox_style.py @@ -1,7 +1,7 @@ from enum import Enum -class AnnotationCheckboxStyle(Enum): +class AnnotationCheckboxStyle(str, Enum): """An enumeration representing different categories. :cvar CIRCLECHECK: "CIRCLE_CHECK" @@ -25,10 +25,11 @@ class AnnotationCheckboxStyle(Enum): CHECKMARK = "CHECK_MARK" TIMESSQUARE = "TIMES_SQUARE" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list( diff --git a/src/signplus/models/annotation_date_time.py b/src/signplus/models/annotation_date_time.py index e5550c3..761a2a9 100644 --- a/src/signplus/models/annotation_date_time.py +++ b/src/signplus/models/annotation_date_time.py @@ -1,12 +1,11 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .annotation_font import AnnotationFont from .annotation_date_time_format import AnnotationDateTimeFormat -@JsonMap({}) class AnnotationDateTime(BaseModel): """Date annotation (null if annotation is not a date) @@ -26,48 +25,21 @@ class AnnotationDateTime(BaseModel): :type format: AnnotationDateTimeFormat, optional """ - def __init__( - self, - size: float = SENTINEL, - font: AnnotationFont = SENTINEL, - color: str = SENTINEL, - auto_fill: bool = SENTINEL, - timezone: str = SENTINEL, - timestamp: int = SENTINEL, - format: AnnotationDateTimeFormat = SENTINEL, - **kwargs, - ): - """Date annotation (null if annotation is not a date) - - :param size: Font size of the text in pt, defaults to None - :type size: float, optional - :param font: font, defaults to None - :type font: AnnotationFont, optional - :param color: Color of the text in hex format, defaults to None - :type color: str, optional - :param auto_fill: Whether the date should be automatically filled, defaults to None - :type auto_fill: bool, optional - :param timezone: Timezone of the date, defaults to None - :type timezone: str, optional - :param timestamp: Unix timestamp of the date, defaults to None - :type timestamp: int, optional - :param format: Format of the date time (DMY_NUMERIC_SLASH is day/month/year with slashes, MDY_NUMERIC_SLASH is month/day/year with slashes, YMD_NUMERIC_SLASH is year/month/day with slashes, DMY_NUMERIC_DASH_SHORT is day/month/year with dashes, DMY_NUMERIC_DASH is day/month/year with dashes, YMD_NUMERIC_DASH is year/month/day with dashes, MDY_TEXT_DASH_SHORT is month/day/year with dashes, MDY_TEXT_SPACE_SHORT is month/day/year with spaces, MDY_TEXT_SPACE is month/day/year with spaces), defaults to None - :type format: AnnotationDateTimeFormat, optional - """ - if size is not SENTINEL: - self.size = size - if font is not SENTINEL: - self.font = self._define_object(font, AnnotationFont) - if color is not SENTINEL: - self.color = color - if auto_fill is not SENTINEL: - self.auto_fill = auto_fill - if timezone is not SENTINEL: - self.timezone = timezone - if timestamp is not SENTINEL: - self.timestamp = timestamp - if format is not SENTINEL: - self.format = self._enum_matching( - format, AnnotationDateTimeFormat.list(), "format" - ) - self._kwargs = kwargs + size: Optional[float] = Field( + default=None, description="Font size of the text in pt" + ) + font: Optional[AnnotationFont] = Field(default=None) + color: Optional[str] = Field( + default=None, description="Color of the text in hex format" + ) + auto_fill: Optional[bool] = Field( + default=None, description="Whether the date should be automatically filled" + ) + timezone: Optional[str] = Field(default=None, description="Timezone of the date") + timestamp: Optional[int] = Field( + default=None, description="Unix timestamp of the date" + ) + format: Optional[AnnotationDateTimeFormat] = Field( + default=None, + description="Format of the date time (DMY_NUMERIC_SLASH is day/month/year with slashes, MDY_NUMERIC_SLASH is month/day/year with slashes, YMD_NUMERIC_SLASH is year/month/day with slashes, DMY_NUMERIC_DASH_SHORT is day/month/year with dashes, DMY_NUMERIC_DASH is day/month/year with dashes, YMD_NUMERIC_DASH is year/month/day with dashes, MDY_TEXT_DASH_SHORT is month/day/year with dashes, MDY_TEXT_SPACE_SHORT is month/day/year with spaces, MDY_TEXT_SPACE is month/day/year with spaces)", + ) diff --git a/src/signplus/models/annotation_date_time_format.py b/src/signplus/models/annotation_date_time_format.py index 686f366..2251cca 100644 --- a/src/signplus/models/annotation_date_time_format.py +++ b/src/signplus/models/annotation_date_time_format.py @@ -1,7 +1,7 @@ from enum import Enum -class AnnotationDateTimeFormat(Enum): +class AnnotationDateTimeFormat(str, Enum): """An enumeration representing different categories. :cvar DMYNUMERICSLASH: "DMY_NUMERIC_SLASH" @@ -34,10 +34,11 @@ class AnnotationDateTimeFormat(Enum): MDYTEXTSPACESHORT = "MDY_TEXT_SPACE_SHORT" MDYTEXTSPACE = "MDY_TEXT_SPACE" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list( diff --git a/src/signplus/models/annotation_font.py b/src/signplus/models/annotation_font.py index f1e9c76..58f39b8 100644 --- a/src/signplus/models/annotation_font.py +++ b/src/signplus/models/annotation_font.py @@ -1,11 +1,10 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .annotation_font_family import AnnotationFontFamily -@JsonMap({}) class AnnotationFont(BaseModel): """AnnotationFont @@ -17,28 +16,10 @@ class AnnotationFont(BaseModel): :type bold: bool, optional """ - def __init__( - self, - family: AnnotationFontFamily = SENTINEL, - italic: bool = SENTINEL, - bold: bool = SENTINEL, - **kwargs, - ): - """AnnotationFont - - :param family: Font family of the text, defaults to None - :type family: AnnotationFontFamily, optional - :param italic: Whether the text is italic, defaults to None - :type italic: bool, optional - :param bold: Whether the text is bold, defaults to None - :type bold: bool, optional - """ - if family is not SENTINEL: - self.family = self._enum_matching( - family, AnnotationFontFamily.list(), "family" - ) - if italic is not SENTINEL: - self.italic = italic - if bold is not SENTINEL: - self.bold = bold - self._kwargs = kwargs + family: Optional[AnnotationFontFamily] = Field( + default=None, description="Font family of the text" + ) + italic: Optional[bool] = Field( + default=None, description="Whether the text is italic" + ) + bold: Optional[bool] = Field(default=None, description="Whether the text is bold") diff --git a/src/signplus/models/annotation_font_family.py b/src/signplus/models/annotation_font_family.py index cd21ac3..f101bf3 100644 --- a/src/signplus/models/annotation_font_family.py +++ b/src/signplus/models/annotation_font_family.py @@ -1,7 +1,7 @@ from enum import Enum -class AnnotationFontFamily(Enum): +class AnnotationFontFamily(str, Enum): """An enumeration representing different categories. :cvar UNKNOWN: "UNKNOWN" @@ -19,10 +19,11 @@ class AnnotationFontFamily(Enum): SANS = "SANS" MONO = "MONO" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list(map(lambda x: x.value, AnnotationFontFamily._member_map_.values())) diff --git a/src/signplus/models/annotation_initials.py b/src/signplus/models/annotation_initials.py index 4136e13..ad80465 100644 --- a/src/signplus/models/annotation_initials.py +++ b/src/signplus/models/annotation_initials.py @@ -1,9 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL -@JsonMap({"id_": "id"}) class AnnotationInitials(BaseModel): """Initials annotation (null if annotation is not initials) @@ -11,12 +10,9 @@ class AnnotationInitials(BaseModel): :type id_: str, optional """ - def __init__(self, id_: str = SENTINEL, **kwargs): - """Initials annotation (null if annotation is not initials) - - :param id_: Unique identifier of the annotation initials, defaults to None - :type id_: str, optional - """ - if id_ is not SENTINEL: - self.id_ = id_ - self._kwargs = kwargs + id_: Optional[str] = Field( + alias="id", + serialization_alias="id", + default=None, + description="Unique identifier of the annotation initials", + ) diff --git a/src/signplus/models/annotation_signature.py b/src/signplus/models/annotation_signature.py index be2e2a1..eef4202 100644 --- a/src/signplus/models/annotation_signature.py +++ b/src/signplus/models/annotation_signature.py @@ -1,9 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL -@JsonMap({"id_": "id"}) class AnnotationSignature(BaseModel): """Signature annotation (null if annotation is not a signature) @@ -11,12 +10,9 @@ class AnnotationSignature(BaseModel): :type id_: str, optional """ - def __init__(self, id_: str = SENTINEL, **kwargs): - """Signature annotation (null if annotation is not a signature) - - :param id_: Unique identifier of the annotation signature, defaults to None - :type id_: str, optional - """ - if id_ is not SENTINEL: - self.id_ = id_ - self._kwargs = kwargs + id_: Optional[str] = Field( + alias="id", + serialization_alias="id", + default=None, + description="Unique identifier of the annotation signature", + ) diff --git a/src/signplus/models/annotation_text.py b/src/signplus/models/annotation_text.py index a95e00b..5375e6f 100644 --- a/src/signplus/models/annotation_text.py +++ b/src/signplus/models/annotation_text.py @@ -1,11 +1,10 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .annotation_font import AnnotationFont -@JsonMap({}) class AnnotationText(BaseModel): """Text annotation (null if annotation is not a text) @@ -23,41 +22,19 @@ class AnnotationText(BaseModel): :type font: AnnotationFont, optional """ - def __init__( - self, - size: float = SENTINEL, - color: float = SENTINEL, - value: str = SENTINEL, - tooltip: str = SENTINEL, - dynamic_field_name: str = SENTINEL, - font: AnnotationFont = SENTINEL, - **kwargs, - ): - """Text annotation (null if annotation is not a text) - - :param size: Font size of the text in pt, defaults to None - :type size: float, optional - :param color: Text color in 32bit representation, defaults to None - :type color: float, optional - :param value: Text content of the annotation, defaults to None - :type value: str, optional - :param tooltip: Tooltip of the annotation, defaults to None - :type tooltip: str, optional - :param dynamic_field_name: Name of the dynamic field, defaults to None - :type dynamic_field_name: str, optional - :param font: font, defaults to None - :type font: AnnotationFont, optional - """ - if size is not SENTINEL: - self.size = size - if color is not SENTINEL: - self.color = color - if value is not SENTINEL: - self.value = value - if tooltip is not SENTINEL: - self.tooltip = tooltip - if dynamic_field_name is not SENTINEL: - self.dynamic_field_name = dynamic_field_name - if font is not SENTINEL: - self.font = self._define_object(font, AnnotationFont) - self._kwargs = kwargs + size: Optional[float] = Field( + default=None, description="Font size of the text in pt" + ) + color: Optional[float] = Field( + default=None, description="Text color in 32bit representation" + ) + value: Optional[str] = Field( + default=None, description="Text content of the annotation" + ) + tooltip: Optional[str] = Field( + default=None, description="Tooltip of the annotation" + ) + dynamic_field_name: Optional[str] = Field( + default=None, description="Name of the dynamic field" + ) + font: Optional[AnnotationFont] = Field(default=None) diff --git a/src/signplus/models/annotation_type.py b/src/signplus/models/annotation_type.py index f375433..7126fbc 100644 --- a/src/signplus/models/annotation_type.py +++ b/src/signplus/models/annotation_type.py @@ -1,7 +1,7 @@ from enum import Enum -class AnnotationType(Enum): +class AnnotationType(str, Enum): """An enumeration representing different categories. :cvar TEXT: "TEXT" @@ -22,10 +22,11 @@ class AnnotationType(Enum): CHECKBOX = "CHECKBOX" DATE = "DATE" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list(map(lambda x: x.value, AnnotationType._member_map_.values())) diff --git a/src/signplus/models/attachment_placeholder.py b/src/signplus/models/attachment_placeholder.py index f798ca8..c8fea7c 100644 --- a/src/signplus/models/attachment_placeholder.py +++ b/src/signplus/models/attachment_placeholder.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .attachment_placeholder_file import AttachmentPlaceholderFile -@JsonMap({"id_": "id"}) class AttachmentPlaceholder(BaseModel): """AttachmentPlaceholder @@ -26,46 +25,24 @@ class AttachmentPlaceholder(BaseModel): :type files: List[AttachmentPlaceholderFile], optional """ - def __init__( - self, - recipient_id: str = SENTINEL, - id_: str = SENTINEL, - name: str = SENTINEL, - hint: str = SENTINEL, - required: bool = SENTINEL, - multiple: bool = SENTINEL, - files: List[AttachmentPlaceholderFile] = SENTINEL, - **kwargs, - ): - """AttachmentPlaceholder - - :param recipient_id: ID of the recipient, defaults to None - :type recipient_id: str, optional - :param id_: ID of the attachment placeholder, defaults to None - :type id_: str, optional - :param name: Name of the attachment placeholder, defaults to None - :type name: str, optional - :param hint: Hint of the attachment placeholder, defaults to None - :type hint: str, optional - :param required: Whether the attachment placeholder is required, defaults to None - :type required: bool, optional - :param multiple: Whether the attachment placeholder can have multiple files, defaults to None - :type multiple: bool, optional - :param files: files, defaults to None - :type files: List[AttachmentPlaceholderFile], optional - """ - if recipient_id is not SENTINEL: - self.recipient_id = recipient_id - if id_ is not SENTINEL: - self.id_ = id_ - if name is not SENTINEL: - self.name = name - if hint is not SENTINEL: - self.hint = hint - if required is not SENTINEL: - self.required = required - if multiple is not SENTINEL: - self.multiple = multiple - if files is not SENTINEL: - self.files = self._define_list(files, AttachmentPlaceholderFile) - self._kwargs = kwargs + recipient_id: Optional[str] = Field(default=None, description="ID of the recipient") + id_: Optional[str] = Field( + alias="id", + serialization_alias="id", + default=None, + description="ID of the attachment placeholder", + ) + name: Optional[str] = Field( + default=None, description="Name of the attachment placeholder" + ) + hint: Optional[str] = Field( + default=None, description="Hint of the attachment placeholder" + ) + required: Optional[bool] = Field( + default=None, description="Whether the attachment placeholder is required" + ) + multiple: Optional[bool] = Field( + default=None, + description="Whether the attachment placeholder can have multiple files", + ) + files: Optional[List[AttachmentPlaceholderFile]] = Field(default=None) diff --git a/src/signplus/models/attachment_placeholder_file.py b/src/signplus/models/attachment_placeholder_file.py index 301da0e..14b889e 100644 --- a/src/signplus/models/attachment_placeholder_file.py +++ b/src/signplus/models/attachment_placeholder_file.py @@ -1,9 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL -@JsonMap({"id_": "id"}) class AttachmentPlaceholderFile(BaseModel): """AttachmentPlaceholderFile @@ -17,31 +16,9 @@ class AttachmentPlaceholderFile(BaseModel): :type mimetype: str, optional """ - def __init__( - self, - id_: str = SENTINEL, - name: str = SENTINEL, - size: int = SENTINEL, - mimetype: str = SENTINEL, - **kwargs - ): - """AttachmentPlaceholderFile - - :param id_: ID of the file, defaults to None - :type id_: str, optional - :param name: Name of the file, defaults to None - :type name: str, optional - :param size: Size of the file in bytes, defaults to None - :type size: int, optional - :param mimetype: MIME type of the file, defaults to None - :type mimetype: str, optional - """ - if id_ is not SENTINEL: - self.id_ = id_ - if name is not SENTINEL: - self.name = name - if size is not SENTINEL: - self.size = size - if mimetype is not SENTINEL: - self.mimetype = mimetype - self._kwargs = kwargs + id_: Optional[str] = Field( + alias="id", serialization_alias="id", default=None, description="ID of the file" + ) + name: Optional[str] = Field(default=None, description="Name of the file") + size: Optional[int] = Field(default=None, description="Size of the file in bytes") + mimetype: Optional[str] = Field(default=None, description="MIME type of the file") diff --git a/src/signplus/models/attachment_placeholder_request.py b/src/signplus/models/attachment_placeholder_request.py index abf1d7e..1ff3496 100644 --- a/src/signplus/models/attachment_placeholder_request.py +++ b/src/signplus/models/attachment_placeholder_request.py @@ -1,9 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL -@JsonMap({"id_": "id"}) class AttachmentPlaceholderRequest(BaseModel): """AttachmentPlaceholderRequest @@ -21,37 +20,16 @@ class AttachmentPlaceholderRequest(BaseModel): :type multiple: bool """ - def __init__( - self, - recipient_id: str, - name: str, - required: bool, - multiple: bool, - id_: str = SENTINEL, - hint: str = SENTINEL, - **kwargs - ): - """AttachmentPlaceholderRequest - - :param recipient_id: ID of the recipient - :type recipient_id: str - :param id_: ID of the attachment placeholder, defaults to None - :type id_: str, optional - :param name: name - :type name: str - :param hint: Hint of the attachment placeholder, defaults to None - :type hint: str, optional - :param required: Whether the attachment placeholder is required - :type required: bool - :param multiple: multiple - :type multiple: bool - """ - self.recipient_id = recipient_id - if id_ is not SENTINEL: - self.id_ = id_ - self.name = name - if hint is not SENTINEL: - self.hint = hint - self.required = required - self.multiple = multiple - self._kwargs = kwargs + recipient_id: str = Field(description="ID of the recipient") + id_: Optional[str] = Field( + alias="id", + serialization_alias="id", + default=None, + description="ID of the attachment placeholder", + ) + name: str + hint: Optional[str] = Field( + default=None, description="Hint of the attachment placeholder" + ) + required: bool = Field(description="Whether the attachment placeholder is required") + multiple: bool diff --git a/src/signplus/models/attachment_placeholders_per_recipient.py b/src/signplus/models/attachment_placeholders_per_recipient.py index 68292e0..b27ef4d 100644 --- a/src/signplus/models/attachment_placeholders_per_recipient.py +++ b/src/signplus/models/attachment_placeholders_per_recipient.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .attachment_placeholder import AttachmentPlaceholder -@JsonMap({}) class AttachmentPlaceholdersPerRecipient(BaseModel): """AttachmentPlaceholdersPerRecipient @@ -18,26 +17,8 @@ class AttachmentPlaceholdersPerRecipient(BaseModel): :type placeholders: List[AttachmentPlaceholder], optional """ - def __init__( - self, - recipient_id: str = SENTINEL, - recipient_name: str = SENTINEL, - placeholders: List[AttachmentPlaceholder] = SENTINEL, - **kwargs, - ): - """AttachmentPlaceholdersPerRecipient - - :param recipient_id: ID of the recipient, defaults to None - :type recipient_id: str, optional - :param recipient_name: Name of the recipient, defaults to None - :type recipient_name: str, optional - :param placeholders: placeholders, defaults to None - :type placeholders: List[AttachmentPlaceholder], optional - """ - if recipient_id is not SENTINEL: - self.recipient_id = recipient_id - if recipient_name is not SENTINEL: - self.recipient_name = recipient_name - if placeholders is not SENTINEL: - self.placeholders = self._define_list(placeholders, AttachmentPlaceholder) - self._kwargs = kwargs + recipient_id: Optional[str] = Field(default=None, description="ID of the recipient") + recipient_name: Optional[str] = Field( + default=None, description="Name of the recipient" + ) + placeholders: Optional[List[AttachmentPlaceholder]] = Field(default=None) diff --git a/src/signplus/models/attachment_settings.py b/src/signplus/models/attachment_settings.py index 78b886c..482f395 100644 --- a/src/signplus/models/attachment_settings.py +++ b/src/signplus/models/attachment_settings.py @@ -1,9 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL -@JsonMap({}) class AttachmentSettings(BaseModel): """AttachmentSettings @@ -11,12 +10,6 @@ class AttachmentSettings(BaseModel): :type visible_to_recipients: bool, optional """ - def __init__(self, visible_to_recipients: bool = SENTINEL, **kwargs): - """AttachmentSettings - - :param visible_to_recipients: Whether the attachment is visible to the recipients, defaults to None - :type visible_to_recipients: bool, optional - """ - if visible_to_recipients is not SENTINEL: - self.visible_to_recipients = visible_to_recipients - self._kwargs = kwargs + visible_to_recipients: Optional[bool] = Field( + default=None, description="Whether the attachment is visible to the recipients" + ) diff --git a/src/signplus/models/create_envelope_from_template_request.py b/src/signplus/models/create_envelope_from_template_request.py index 98b825b..30db60b 100644 --- a/src/signplus/models/create_envelope_from_template_request.py +++ b/src/signplus/models/create_envelope_from_template_request.py @@ -1,9 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL -@JsonMap({}) class CreateEnvelopeFromTemplateRequest(BaseModel): """CreateEnvelopeFromTemplateRequest @@ -15,27 +14,13 @@ class CreateEnvelopeFromTemplateRequest(BaseModel): :type sandbox: bool, optional """ - def __init__( - self, name: str, comment: str = SENTINEL, sandbox: bool = SENTINEL, **kwargs - ): - """CreateEnvelopeFromTemplateRequest - - :param name: Name of the envelope - :type name: str - :param comment: Comment for the envelope, defaults to None - :type comment: str, optional - :param sandbox: Whether the envelope is created in sandbox mode, defaults to None - :type sandbox: bool, optional - """ - self.name = self._define_str( - "name", - name, - pattern="^[a-zA-Z0-9][a-zA-Z0-9 ]*[a-zA-Z0-9]$", - min_length=2, - max_length=256, - ) - if comment is not SENTINEL: - self.comment = comment - if sandbox is not SENTINEL: - self.sandbox = sandbox - self._kwargs = kwargs + name: str = Field( + description="Name of the envelope", + pattern=r"^[a-zA-Z0-9][a-zA-Z0-9 ]*[a-zA-Z0-9]$", + min_length=2, + max_length=256, + ) + comment: Optional[str] = Field(default=None, description="Comment for the envelope") + sandbox: Optional[bool] = Field( + default=None, description="Whether the envelope is created in sandbox mode" + ) diff --git a/src/signplus/models/create_envelope_request.py b/src/signplus/models/create_envelope_request.py index 05f5e83..6227a16 100644 --- a/src/signplus/models/create_envelope_request.py +++ b/src/signplus/models/create_envelope_request.py @@ -1,11 +1,10 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .envelope_legality_level import EnvelopeLegalityLevel -@JsonMap({}) class CreateEnvelopeRequest(BaseModel): """CreateEnvelopeRequest @@ -21,42 +20,19 @@ class CreateEnvelopeRequest(BaseModel): :type sandbox: bool, optional """ - def __init__( - self, - name: str, - legality_level: EnvelopeLegalityLevel, - expires_at: int = SENTINEL, - comment: str = SENTINEL, - sandbox: bool = SENTINEL, - **kwargs, - ): - """CreateEnvelopeRequest - - :param name: Name of the envelope - :type name: str - :param legality_level: Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes) - :type legality_level: EnvelopeLegalityLevel - :param expires_at: Unix timestamp of the expiration date, defaults to None - :type expires_at: int, optional - :param comment: Comment for the envelope, defaults to None - :type comment: str, optional - :param sandbox: Whether the envelope is created in sandbox mode, defaults to None - :type sandbox: bool, optional - """ - self.name = self._define_str( - "name", - name, - pattern="^[a-zA-Z0-9][a-zA-Z0-9 ]*[a-zA-Z0-9]$", - min_length=2, - max_length=256, - ) - self.legality_level = self._enum_matching( - legality_level, EnvelopeLegalityLevel.list(), "legality_level" - ) - if expires_at is not SENTINEL: - self.expires_at = expires_at - if comment is not SENTINEL: - self.comment = comment - if sandbox is not SENTINEL: - self.sandbox = sandbox - self._kwargs = kwargs + name: str = Field( + description="Name of the envelope", + pattern=r"^[a-zA-Z0-9][a-zA-Z0-9 ]*[a-zA-Z0-9]$", + min_length=2, + max_length=256, + ) + legality_level: EnvelopeLegalityLevel = Field( + description="Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes)" + ) + expires_at: Optional[int] = Field( + default=None, description="Unix timestamp of the expiration date" + ) + comment: Optional[str] = Field(default=None, description="Comment for the envelope") + sandbox: Optional[bool] = Field( + default=None, description="Whether the envelope is created in sandbox mode" + ) diff --git a/src/signplus/models/create_template_request.py b/src/signplus/models/create_template_request.py index 1f0b710..560066e 100644 --- a/src/signplus/models/create_template_request.py +++ b/src/signplus/models/create_template_request.py @@ -1,8 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -@JsonMap({}) class CreateTemplateRequest(BaseModel): """CreateTemplateRequest @@ -10,17 +10,6 @@ class CreateTemplateRequest(BaseModel): :type name: str """ - def __init__(self, name: str, **kwargs): - """CreateTemplateRequest - - :param name: name - :type name: str - """ - self.name = self._define_str( - "name", - name, - pattern="^[a-zA-Z0-9][a-zA-Z0-9 ]*[a-zA-Z0-9]$", - min_length=2, - max_length=256, - ) - self._kwargs = kwargs + name: str = Field( + pattern=r"^[a-zA-Z0-9][a-zA-Z0-9 ]*[a-zA-Z0-9]$", min_length=2, max_length=256 + ) diff --git a/src/signplus/models/create_webhook_request.py b/src/signplus/models/create_webhook_request.py index fa43dcf..43e2643 100644 --- a/src/signplus/models/create_webhook_request.py +++ b/src/signplus/models/create_webhook_request.py @@ -1,10 +1,10 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel from .webhook_event import WebhookEvent -@JsonMap({}) class CreateWebhookRequest(BaseModel): """CreateWebhookRequest @@ -14,14 +14,5 @@ class CreateWebhookRequest(BaseModel): :type target: str """ - def __init__(self, event: WebhookEvent, target: str, **kwargs): - """CreateWebhookRequest - - :param event: Event of the webhook - :type event: WebhookEvent - :param target: URL of the webhook target - :type target: str - """ - self.event = self._enum_matching(event, WebhookEvent.list(), "event") - self.target = target - self._kwargs = kwargs + event: WebhookEvent = Field(description="Event of the webhook") + target: str = Field(description="URL of the webhook target") diff --git a/src/signplus/models/document.py b/src/signplus/models/document.py index 45d5940..3c9df6b 100644 --- a/src/signplus/models/document.py +++ b/src/signplus/models/document.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .page import Page -@JsonMap({"id_": "id"}) class Document(BaseModel): """Document @@ -22,36 +21,19 @@ class Document(BaseModel): :type pages: List[Page], optional """ - def __init__( - self, - id_: str = SENTINEL, - name: str = SENTINEL, - filename: str = SENTINEL, - page_count: int = SENTINEL, - pages: List[Page] = SENTINEL, - **kwargs, - ): - """Document - - :param id_: Unique identifier of the document, defaults to None - :type id_: str, optional - :param name: Name of the document, defaults to None - :type name: str, optional - :param filename: Filename of the document, defaults to None - :type filename: str, optional - :param page_count: Number of pages in the document, defaults to None - :type page_count: int, optional - :param pages: List of pages in the document, defaults to None - :type pages: List[Page], optional - """ - if id_ is not SENTINEL: - self.id_ = id_ - if name is not SENTINEL: - self.name = name - if filename is not SENTINEL: - self.filename = filename - if page_count is not SENTINEL: - self.page_count = page_count - if pages is not SENTINEL: - self.pages = self._define_list(pages, Page) - self._kwargs = kwargs + id_: Optional[str] = Field( + alias="id", + serialization_alias="id", + default=None, + description="Unique identifier of the document", + ) + name: Optional[str] = Field(default=None, description="Name of the document") + filename: Optional[str] = Field( + default=None, description="Filename of the document" + ) + page_count: Optional[int] = Field( + default=None, description="Number of pages in the document" + ) + pages: Optional[List[Page]] = Field( + default=None, description="List of pages in the document" + ) diff --git a/src/signplus/models/dynamic_field.py b/src/signplus/models/dynamic_field.py index e02ea86..5f89953 100644 --- a/src/signplus/models/dynamic_field.py +++ b/src/signplus/models/dynamic_field.py @@ -1,9 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL -@JsonMap({}) class DynamicField(BaseModel): """DynamicField @@ -13,16 +12,5 @@ class DynamicField(BaseModel): :type value: str, optional """ - def __init__(self, name: str = SENTINEL, value: str = SENTINEL, **kwargs): - """DynamicField - - :param name: Name of the dynamic field, defaults to None - :type name: str, optional - :param value: Value of the dynamic field, defaults to None - :type value: str, optional - """ - if name is not SENTINEL: - self.name = name - if value is not SENTINEL: - self.value = value - self._kwargs = kwargs + name: Optional[str] = Field(default=None, description="Name of the dynamic field") + value: Optional[str] = Field(default=None, description="Value of the dynamic field") diff --git a/src/signplus/models/envelope.py b/src/signplus/models/envelope.py index 6faa4bb..e65bada 100644 --- a/src/signplus/models/envelope.py +++ b/src/signplus/models/envelope.py @@ -1,8 +1,8 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .envelope_flow_type import EnvelopeFlowType from .envelope_legality_level import EnvelopeLegalityLevel from .envelope_status import EnvelopeStatus @@ -12,7 +12,6 @@ from .envelope_attachments import EnvelopeAttachments -@JsonMap({"id_": "id"}) class Envelope(BaseModel): """Envelope @@ -50,95 +49,44 @@ class Envelope(BaseModel): :type attachments: EnvelopeAttachments, optional """ - def __init__( - self, - id_: str = SENTINEL, - name: str = SENTINEL, - comment: str = SENTINEL, - pages: int = SENTINEL, - flow_type: EnvelopeFlowType = SENTINEL, - legality_level: EnvelopeLegalityLevel = SENTINEL, - status: EnvelopeStatus = SENTINEL, - created_at: int = SENTINEL, - updated_at: int = SENTINEL, - expires_at: int = SENTINEL, - num_recipients: int = SENTINEL, - is_duplicable: bool = SENTINEL, - signing_steps: List[SigningStep] = SENTINEL, - documents: List[Document] = SENTINEL, - notification: EnvelopeNotification = SENTINEL, - attachments: EnvelopeAttachments = SENTINEL, - **kwargs, - ): - """Envelope - - :param id_: Unique identifier of the envelope, defaults to None - :type id_: str, optional - :param name: Name of the envelope, defaults to None - :type name: str, optional - :param comment: Comment for the envelope, defaults to None - :type comment: str, optional - :param pages: Total number of pages in the envelope, defaults to None - :type pages: int, optional - :param flow_type: Flow type of the envelope (REQUEST_SIGNATURE is a request for signature, SIGN_MYSELF is a self-signing flow), defaults to None - :type flow_type: EnvelopeFlowType, optional - :param legality_level: Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes), defaults to None - :type legality_level: EnvelopeLegalityLevel, optional - :param status: Status of the envelope, defaults to None - :type status: EnvelopeStatus, optional - :param created_at: Unix timestamp of the creation date, defaults to None - :type created_at: int, optional - :param updated_at: Unix timestamp of the last modification date, defaults to None - :type updated_at: int, optional - :param expires_at: Unix timestamp of the expiration date, defaults to None - :type expires_at: int, optional - :param num_recipients: Number of recipients in the envelope, defaults to None - :type num_recipients: int, optional - :param is_duplicable: Whether the envelope can be duplicated, defaults to None - :type is_duplicable: bool, optional - :param signing_steps: signing_steps, defaults to None - :type signing_steps: List[SigningStep], optional - :param documents: documents, defaults to None - :type documents: List[Document], optional - :param notification: notification, defaults to None - :type notification: EnvelopeNotification, optional - :param attachments: attachments, defaults to None - :type attachments: EnvelopeAttachments, optional - """ - if id_ is not SENTINEL: - self.id_ = id_ - if name is not SENTINEL: - self.name = name - if comment is not SENTINEL: - self.comment = comment - if pages is not SENTINEL: - self.pages = pages - if flow_type is not SENTINEL: - self.flow_type = self._enum_matching( - flow_type, EnvelopeFlowType.list(), "flow_type" - ) - if legality_level is not SENTINEL: - self.legality_level = self._enum_matching( - legality_level, EnvelopeLegalityLevel.list(), "legality_level" - ) - if status is not SENTINEL: - self.status = self._enum_matching(status, EnvelopeStatus.list(), "status") - if created_at is not SENTINEL: - self.created_at = created_at - if updated_at is not SENTINEL: - self.updated_at = updated_at - if expires_at is not SENTINEL: - self.expires_at = expires_at - if num_recipients is not SENTINEL: - self.num_recipients = num_recipients - if is_duplicable is not SENTINEL: - self.is_duplicable = is_duplicable - if signing_steps is not SENTINEL: - self.signing_steps = self._define_list(signing_steps, SigningStep) - if documents is not SENTINEL: - self.documents = self._define_list(documents, Document) - if notification is not SENTINEL: - self.notification = self._define_object(notification, EnvelopeNotification) - if attachments is not SENTINEL: - self.attachments = self._define_object(attachments, EnvelopeAttachments) - self._kwargs = kwargs + id_: Optional[str] = Field( + alias="id", + serialization_alias="id", + default=None, + description="Unique identifier of the envelope", + ) + name: Optional[str] = Field(default=None, description="Name of the envelope") + comment: Optional[str] = Field(default=None, description="Comment for the envelope") + pages: Optional[int] = Field( + default=None, description="Total number of pages in the envelope" + ) + flow_type: Optional[EnvelopeFlowType] = Field( + default=None, + description="Flow type of the envelope (REQUEST_SIGNATURE is a request for signature, SIGN_MYSELF is a self-signing flow)", + ) + legality_level: Optional[EnvelopeLegalityLevel] = Field( + default=None, + description="Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes)", + ) + status: Optional[EnvelopeStatus] = Field( + default=None, description="Status of the envelope" + ) + created_at: Optional[int] = Field( + default=None, description="Unix timestamp of the creation date" + ) + updated_at: Optional[int] = Field( + default=None, description="Unix timestamp of the last modification date" + ) + expires_at: Optional[int] = Field( + default=None, description="Unix timestamp of the expiration date" + ) + num_recipients: Optional[int] = Field( + default=None, description="Number of recipients in the envelope" + ) + is_duplicable: Optional[bool] = Field( + default=None, description="Whether the envelope can be duplicated" + ) + signing_steps: Optional[List[SigningStep]] = Field(default=None) + documents: Optional[List[Document]] = Field(default=None) + notification: Optional[EnvelopeNotification] = Field(default=None) + attachments: Optional[EnvelopeAttachments] = Field(default=None) diff --git a/src/signplus/models/envelope_attachments.py b/src/signplus/models/envelope_attachments.py index bb4ea2e..a0f9609 100644 --- a/src/signplus/models/envelope_attachments.py +++ b/src/signplus/models/envelope_attachments.py @@ -1,13 +1,12 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .attachment_settings import AttachmentSettings from .attachment_placeholders_per_recipient import AttachmentPlaceholdersPerRecipient -@JsonMap({}) class EnvelopeAttachments(BaseModel): """EnvelopeAttachments @@ -17,23 +16,5 @@ class EnvelopeAttachments(BaseModel): :type recipients: List[AttachmentPlaceholdersPerRecipient], optional """ - def __init__( - self, - settings: AttachmentSettings = SENTINEL, - recipients: List[AttachmentPlaceholdersPerRecipient] = SENTINEL, - **kwargs, - ): - """EnvelopeAttachments - - :param settings: settings, defaults to None - :type settings: AttachmentSettings, optional - :param recipients: recipients, defaults to None - :type recipients: List[AttachmentPlaceholdersPerRecipient], optional - """ - if settings is not SENTINEL: - self.settings = self._define_object(settings, AttachmentSettings) - if recipients is not SENTINEL: - self.recipients = self._define_list( - recipients, AttachmentPlaceholdersPerRecipient - ) - self._kwargs = kwargs + settings: Optional[AttachmentSettings] = Field(default=None) + recipients: Optional[List[AttachmentPlaceholdersPerRecipient]] = Field(default=None) diff --git a/src/signplus/models/envelope_flow_type.py b/src/signplus/models/envelope_flow_type.py index eea3b4d..f19224a 100644 --- a/src/signplus/models/envelope_flow_type.py +++ b/src/signplus/models/envelope_flow_type.py @@ -1,7 +1,7 @@ from enum import Enum -class EnvelopeFlowType(Enum): +class EnvelopeFlowType(str, Enum): """An enumeration representing different categories. :cvar REQUESTSIGNATURE: "REQUEST_SIGNATURE" @@ -13,10 +13,11 @@ class EnvelopeFlowType(Enum): REQUESTSIGNATURE = "REQUEST_SIGNATURE" SIGNMYSELF = "SIGN_MYSELF" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list(map(lambda x: x.value, EnvelopeFlowType._member_map_.values())) diff --git a/src/signplus/models/envelope_legality_level.py b/src/signplus/models/envelope_legality_level.py index dfb57e5..4e12111 100644 --- a/src/signplus/models/envelope_legality_level.py +++ b/src/signplus/models/envelope_legality_level.py @@ -1,7 +1,7 @@ from enum import Enum -class EnvelopeLegalityLevel(Enum): +class EnvelopeLegalityLevel(str, Enum): """An enumeration representing different categories. :cvar SES: "SES" @@ -16,10 +16,11 @@ class EnvelopeLegalityLevel(Enum): QESEIDAS = "QES_EIDAS" QESZERTES = "QES_ZERTES" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list(map(lambda x: x.value, EnvelopeLegalityLevel._member_map_.values())) diff --git a/src/signplus/models/envelope_notification.py b/src/signplus/models/envelope_notification.py index 58fb406..94ca0aa 100644 --- a/src/signplus/models/envelope_notification.py +++ b/src/signplus/models/envelope_notification.py @@ -1,9 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL -@JsonMap({}) class EnvelopeNotification(BaseModel): """EnvelopeNotification @@ -15,26 +14,12 @@ class EnvelopeNotification(BaseModel): :type reminder_interval: int, optional """ - def __init__( - self, - subject: str = SENTINEL, - message: str = SENTINEL, - reminder_interval: int = SENTINEL, - **kwargs - ): - """EnvelopeNotification - - :param subject: Subject of the notification, defaults to None - :type subject: str, optional - :param message: Message of the notification, defaults to None - :type message: str, optional - :param reminder_interval: Interval in days to send reminder, defaults to None - :type reminder_interval: int, optional - """ - if subject is not SENTINEL: - self.subject = subject - if message is not SENTINEL: - self.message = message - if reminder_interval is not SENTINEL: - self.reminder_interval = reminder_interval - self._kwargs = kwargs + subject: Optional[str] = Field( + default=None, description="Subject of the notification" + ) + message: Optional[str] = Field( + default=None, description="Message of the notification" + ) + reminder_interval: Optional[int] = Field( + default=None, description="Interval in days to send reminder" + ) diff --git a/src/signplus/models/envelope_order_field.py b/src/signplus/models/envelope_order_field.py index 11f6b0b..10b727c 100644 --- a/src/signplus/models/envelope_order_field.py +++ b/src/signplus/models/envelope_order_field.py @@ -1,7 +1,7 @@ from enum import Enum -class EnvelopeOrderField(Enum): +class EnvelopeOrderField(str, Enum): """An enumeration representing different categories. :cvar CREATIONDATE: "CREATION_DATE" @@ -22,10 +22,11 @@ class EnvelopeOrderField(Enum): STATUS = "STATUS" LASTDOCUMENTCHANGE = "LAST_DOCUMENT_CHANGE" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list(map(lambda x: x.value, EnvelopeOrderField._member_map_.values())) diff --git a/src/signplus/models/envelope_status.py b/src/signplus/models/envelope_status.py index 93c98d3..89bca9f 100644 --- a/src/signplus/models/envelope_status.py +++ b/src/signplus/models/envelope_status.py @@ -1,7 +1,7 @@ from enum import Enum -class EnvelopeStatus(Enum): +class EnvelopeStatus(str, Enum): """An enumeration representing different categories. :cvar DRAFT: "DRAFT" @@ -28,10 +28,11 @@ class EnvelopeStatus(Enum): VOIDED = "VOIDED" PENDING = "PENDING" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list(map(lambda x: x.value, EnvelopeStatus._member_map_.values())) diff --git a/src/signplus/models/list_envelope_document_annotations_response.py b/src/signplus/models/list_envelope_document_annotations_response.py index 2b05e6d..be6ae08 100644 --- a/src/signplus/models/list_envelope_document_annotations_response.py +++ b/src/signplus/models/list_envelope_document_annotations_response.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .annotation import Annotation -@JsonMap({}) class ListEnvelopeDocumentAnnotationsResponse(BaseModel): """ListEnvelopeDocumentAnnotationsResponse @@ -14,12 +13,4 @@ class ListEnvelopeDocumentAnnotationsResponse(BaseModel): :type annotations: List[Annotation], optional """ - def __init__(self, annotations: List[Annotation] = SENTINEL, **kwargs): - """ListEnvelopeDocumentAnnotationsResponse - - :param annotations: annotations, defaults to None - :type annotations: List[Annotation], optional - """ - if annotations is not SENTINEL: - self.annotations = self._define_list(annotations, Annotation) - self._kwargs = kwargs + annotations: Optional[List[Annotation]] = Field(default=None) diff --git a/src/signplus/models/list_envelope_documents_response.py b/src/signplus/models/list_envelope_documents_response.py index b0a4e0b..7e9d826 100644 --- a/src/signplus/models/list_envelope_documents_response.py +++ b/src/signplus/models/list_envelope_documents_response.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .document import Document -@JsonMap({}) class ListEnvelopeDocumentsResponse(BaseModel): """ListEnvelopeDocumentsResponse @@ -14,12 +13,4 @@ class ListEnvelopeDocumentsResponse(BaseModel): :type documents: List[Document], optional """ - def __init__(self, documents: List[Document] = SENTINEL, **kwargs): - """ListEnvelopeDocumentsResponse - - :param documents: documents, defaults to None - :type documents: List[Document], optional - """ - if documents is not SENTINEL: - self.documents = self._define_list(documents, Document) - self._kwargs = kwargs + documents: Optional[List[Document]] = Field(default=None) diff --git a/src/signplus/models/list_envelopes_request.py b/src/signplus/models/list_envelopes_request.py index d06292a..53de97c 100644 --- a/src/signplus/models/list_envelopes_request.py +++ b/src/signplus/models/list_envelopes_request.py @@ -1,13 +1,12 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .envelope_status import EnvelopeStatus from .envelope_order_field import EnvelopeOrderField -@JsonMap({}) class ListEnvelopesRequest(BaseModel): """ListEnvelopesRequest @@ -47,98 +46,38 @@ class ListEnvelopesRequest(BaseModel): :type include_trash: bool, optional """ - def __init__( - self, - name: str = SENTINEL, - tags: List[str] = SENTINEL, - comment: str = SENTINEL, - ids: List[str] = SENTINEL, - statuses: List[EnvelopeStatus] = SENTINEL, - folder_ids: List[str] = SENTINEL, - only_root_folder: bool = SENTINEL, - date_from: int = SENTINEL, - date_to: int = SENTINEL, - uid: str = SENTINEL, - first: int = SENTINEL, - last: int = SENTINEL, - after: str = SENTINEL, - before: str = SENTINEL, - order_field: EnvelopeOrderField = SENTINEL, - ascending: bool = SENTINEL, - include_trash: bool = SENTINEL, - **kwargs, - ): - """ListEnvelopesRequest - - :param name: Name of the envelope, defaults to None - :type name: str, optional - :param tags: List of tags, defaults to None - :type tags: List[str], optional - :param comment: Comment of the envelope, defaults to None - :type comment: str, optional - :param ids: List of envelope IDs, defaults to None - :type ids: List[str], optional - :param statuses: List of envelope statuses, defaults to None - :type statuses: List[EnvelopeStatus], optional - :param folder_ids: List of folder IDs, defaults to None - :type folder_ids: List[str], optional - :param only_root_folder: Whether to only list envelopes in the root folder, defaults to None - :type only_root_folder: bool, optional - :param date_from: Unix timestamp of the start date, defaults to None - :type date_from: int, optional - :param date_to: Unix timestamp of the end date, defaults to None - :type date_to: int, optional - :param uid: Unique identifier of the user, defaults to None - :type uid: str, optional - :param first: first, defaults to None - :type first: int, optional - :param last: last, defaults to None - :type last: int, optional - :param after: after, defaults to None - :type after: str, optional - :param before: before, defaults to None - :type before: str, optional - :param order_field: Field to order envelopes by, defaults to None - :type order_field: EnvelopeOrderField, optional - :param ascending: Whether to order envelopes in ascending order, defaults to None - :type ascending: bool, optional - :param include_trash: Whether to include envelopes in the trash, defaults to None - :type include_trash: bool, optional - """ - if name is not SENTINEL: - self.name = name - if tags is not SENTINEL: - self.tags = tags - if comment is not SENTINEL: - self.comment = comment - if ids is not SENTINEL: - self.ids = ids - if statuses is not SENTINEL: - self.statuses = self._define_list(statuses, EnvelopeStatus) - if folder_ids is not SENTINEL: - self.folder_ids = folder_ids - if only_root_folder is not SENTINEL: - self.only_root_folder = only_root_folder - if date_from is not SENTINEL: - self.date_from = date_from - if date_to is not SENTINEL: - self.date_to = date_to - if uid is not SENTINEL: - self.uid = uid - if first is not SENTINEL: - self.first = first - if last is not SENTINEL: - self.last = last - if after is not SENTINEL: - self.after = after - if before is not SENTINEL: - self.before = before - if order_field is not SENTINEL: - self.order_field = self._enum_matching( - order_field, EnvelopeOrderField.list(), "order_field" - ) - if ascending is not SENTINEL: - self.ascending = ascending - if include_trash is not SENTINEL: - self.include_trash = include_trash - self._kwargs = kwargs + name: Optional[str] = Field(default=None, description="Name of the envelope") + tags: Optional[List[str]] = Field(default=None, description="List of tags") + comment: Optional[str] = Field(default=None, description="Comment of the envelope") + ids: Optional[List[str]] = Field(default=None, description="List of envelope IDs") + statuses: Optional[List[EnvelopeStatus]] = Field( + default=None, description="List of envelope statuses" + ) + folder_ids: Optional[List[str]] = Field( + default=None, description="List of folder IDs" + ) + only_root_folder: Optional[bool] = Field( + default=None, description="Whether to only list envelopes in the root folder" + ) + date_from: Optional[int] = Field( + default=None, description="Unix timestamp of the start date" + ) + date_to: Optional[int] = Field( + default=None, description="Unix timestamp of the end date" + ) + uid: Optional[str] = Field( + default=None, description="Unique identifier of the user" + ) + first: Optional[int] = Field(default=None) + last: Optional[int] = Field(default=None) + after: Optional[str] = Field(default=None) + before: Optional[str] = Field(default=None) + order_field: Optional[EnvelopeOrderField] = Field( + default=None, description="Field to order envelopes by" + ) + ascending: Optional[bool] = Field( + default=None, description="Whether to order envelopes in ascending order" + ) + include_trash: Optional[bool] = Field( + default=None, description="Whether to include envelopes in the trash" + ) diff --git a/src/signplus/models/list_envelopes_response.py b/src/signplus/models/list_envelopes_response.py index 48d8d92..6828685 100644 --- a/src/signplus/models/list_envelopes_response.py +++ b/src/signplus/models/list_envelopes_response.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .envelope import Envelope -@JsonMap({}) class ListEnvelopesResponse(BaseModel): """ListEnvelopesResponse @@ -18,26 +17,10 @@ class ListEnvelopesResponse(BaseModel): :type envelopes: List[Envelope], optional """ - def __init__( - self, - has_next_page: bool = SENTINEL, - has_previous_page: bool = SENTINEL, - envelopes: List[Envelope] = SENTINEL, - **kwargs, - ): - """ListEnvelopesResponse - - :param has_next_page: Whether there is a next page, defaults to None - :type has_next_page: bool, optional - :param has_previous_page: Whether there is a previous page, defaults to None - :type has_previous_page: bool, optional - :param envelopes: envelopes, defaults to None - :type envelopes: List[Envelope], optional - """ - if has_next_page is not SENTINEL: - self.has_next_page = has_next_page - if has_previous_page is not SENTINEL: - self.has_previous_page = has_previous_page - if envelopes is not SENTINEL: - self.envelopes = self._define_list(envelopes, Envelope) - self._kwargs = kwargs + has_next_page: Optional[bool] = Field( + default=None, description="Whether there is a next page" + ) + has_previous_page: Optional[bool] = Field( + default=None, description="Whether there is a previous page" + ) + envelopes: Optional[List[Envelope]] = Field(default=None) diff --git a/src/signplus/models/list_template_annotations_response.py b/src/signplus/models/list_template_annotations_response.py index 9639320..1605235 100644 --- a/src/signplus/models/list_template_annotations_response.py +++ b/src/signplus/models/list_template_annotations_response.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .annotation import Annotation -@JsonMap({}) class ListTemplateAnnotationsResponse(BaseModel): """ListTemplateAnnotationsResponse @@ -14,12 +13,4 @@ class ListTemplateAnnotationsResponse(BaseModel): :type annotations: List[Annotation], optional """ - def __init__(self, annotations: List[Annotation] = SENTINEL, **kwargs): - """ListTemplateAnnotationsResponse - - :param annotations: annotations, defaults to None - :type annotations: List[Annotation], optional - """ - if annotations is not SENTINEL: - self.annotations = self._define_list(annotations, Annotation) - self._kwargs = kwargs + annotations: Optional[List[Annotation]] = Field(default=None) diff --git a/src/signplus/models/list_template_document_annotations_response.py b/src/signplus/models/list_template_document_annotations_response.py index 99ab9f5..42ce2a4 100644 --- a/src/signplus/models/list_template_document_annotations_response.py +++ b/src/signplus/models/list_template_document_annotations_response.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .annotation import Annotation -@JsonMap({}) class ListTemplateDocumentAnnotationsResponse(BaseModel): """ListTemplateDocumentAnnotationsResponse @@ -14,12 +13,4 @@ class ListTemplateDocumentAnnotationsResponse(BaseModel): :type annotations: List[Annotation], optional """ - def __init__(self, annotations: List[Annotation] = SENTINEL, **kwargs): - """ListTemplateDocumentAnnotationsResponse - - :param annotations: annotations, defaults to None - :type annotations: List[Annotation], optional - """ - if annotations is not SENTINEL: - self.annotations = self._define_list(annotations, Annotation) - self._kwargs = kwargs + annotations: Optional[List[Annotation]] = Field(default=None) diff --git a/src/signplus/models/list_template_documents_response.py b/src/signplus/models/list_template_documents_response.py index 8470562..348d096 100644 --- a/src/signplus/models/list_template_documents_response.py +++ b/src/signplus/models/list_template_documents_response.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .document import Document -@JsonMap({}) class ListTemplateDocumentsResponse(BaseModel): """ListTemplateDocumentsResponse @@ -14,12 +13,4 @@ class ListTemplateDocumentsResponse(BaseModel): :type documents: List[Document], optional """ - def __init__(self, documents: List[Document] = SENTINEL, **kwargs): - """ListTemplateDocumentsResponse - - :param documents: documents, defaults to None - :type documents: List[Document], optional - """ - if documents is not SENTINEL: - self.documents = self._define_list(documents, Document) - self._kwargs = kwargs + documents: Optional[List[Document]] = Field(default=None) diff --git a/src/signplus/models/list_templates_request.py b/src/signplus/models/list_templates_request.py index b1c448a..030645e 100644 --- a/src/signplus/models/list_templates_request.py +++ b/src/signplus/models/list_templates_request.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .template_order_field import TemplateOrderField -@JsonMap({}) class ListTemplatesRequest(BaseModel): """ListTemplatesRequest @@ -30,58 +29,16 @@ class ListTemplatesRequest(BaseModel): :type ascending: bool, optional """ - def __init__( - self, - name: str = SENTINEL, - tags: List[str] = SENTINEL, - ids: List[str] = SENTINEL, - first: int = SENTINEL, - last: int = SENTINEL, - after: str = SENTINEL, - before: str = SENTINEL, - order_field: TemplateOrderField = SENTINEL, - ascending: bool = SENTINEL, - **kwargs, - ): - """ListTemplatesRequest - - :param name: Name of the template, defaults to None - :type name: str, optional - :param tags: List of tag templates, defaults to None - :type tags: List[str], optional - :param ids: List of templates IDs, defaults to None - :type ids: List[str], optional - :param first: first, defaults to None - :type first: int, optional - :param last: last, defaults to None - :type last: int, optional - :param after: after, defaults to None - :type after: str, optional - :param before: before, defaults to None - :type before: str, optional - :param order_field: Field to order templates by, defaults to None - :type order_field: TemplateOrderField, optional - :param ascending: Whether to order templates in ascending order, defaults to None - :type ascending: bool, optional - """ - if name is not SENTINEL: - self.name = name - if tags is not SENTINEL: - self.tags = tags - if ids is not SENTINEL: - self.ids = ids - if first is not SENTINEL: - self.first = first - if last is not SENTINEL: - self.last = last - if after is not SENTINEL: - self.after = after - if before is not SENTINEL: - self.before = before - if order_field is not SENTINEL: - self.order_field = self._enum_matching( - order_field, TemplateOrderField.list(), "order_field" - ) - if ascending is not SENTINEL: - self.ascending = ascending - self._kwargs = kwargs + name: Optional[str] = Field(default=None, description="Name of the template") + tags: Optional[List[str]] = Field(default=None, description="List of tag templates") + ids: Optional[List[str]] = Field(default=None, description="List of templates IDs") + first: Optional[int] = Field(default=None) + last: Optional[int] = Field(default=None) + after: Optional[str] = Field(default=None) + before: Optional[str] = Field(default=None) + order_field: Optional[TemplateOrderField] = Field( + default=None, description="Field to order templates by" + ) + ascending: Optional[bool] = Field( + default=None, description="Whether to order templates in ascending order" + ) diff --git a/src/signplus/models/list_templates_response.py b/src/signplus/models/list_templates_response.py index b5d5550..9d84295 100644 --- a/src/signplus/models/list_templates_response.py +++ b/src/signplus/models/list_templates_response.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .template import Template -@JsonMap({}) class ListTemplatesResponse(BaseModel): """ListTemplatesResponse @@ -18,26 +17,10 @@ class ListTemplatesResponse(BaseModel): :type templates: List[Template], optional """ - def __init__( - self, - has_next_page: bool = SENTINEL, - has_previous_page: bool = SENTINEL, - templates: List[Template] = SENTINEL, - **kwargs, - ): - """ListTemplatesResponse - - :param has_next_page: Whether there is a next page, defaults to None - :type has_next_page: bool, optional - :param has_previous_page: Whether there is a previous page, defaults to None - :type has_previous_page: bool, optional - :param templates: templates, defaults to None - :type templates: List[Template], optional - """ - if has_next_page is not SENTINEL: - self.has_next_page = has_next_page - if has_previous_page is not SENTINEL: - self.has_previous_page = has_previous_page - if templates is not SENTINEL: - self.templates = self._define_list(templates, Template) - self._kwargs = kwargs + has_next_page: Optional[bool] = Field( + default=None, description="Whether there is a next page" + ) + has_previous_page: Optional[bool] = Field( + default=None, description="Whether there is a previous page" + ) + templates: Optional[List[Template]] = Field(default=None) diff --git a/src/signplus/models/list_webhooks_request.py b/src/signplus/models/list_webhooks_request.py index 873ff0d..246d6a3 100644 --- a/src/signplus/models/list_webhooks_request.py +++ b/src/signplus/models/list_webhooks_request.py @@ -1,11 +1,10 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .webhook_event import WebhookEvent -@JsonMap({}) class ListWebhooksRequest(BaseModel): """ListWebhooksRequest @@ -15,18 +14,7 @@ class ListWebhooksRequest(BaseModel): :type event: WebhookEvent, optional """ - def __init__( - self, webhook_id: str = SENTINEL, event: WebhookEvent = SENTINEL, **kwargs - ): - """ListWebhooksRequest - - :param webhook_id: ID of the webhook, defaults to None - :type webhook_id: str, optional - :param event: Event of the webhook, defaults to None - :type event: WebhookEvent, optional - """ - if webhook_id is not SENTINEL: - self.webhook_id = webhook_id - if event is not SENTINEL: - self.event = self._enum_matching(event, WebhookEvent.list(), "event") - self._kwargs = kwargs + webhook_id: Optional[str] = Field(default=None, description="ID of the webhook") + event: Optional[WebhookEvent] = Field( + default=None, description="Event of the webhook" + ) diff --git a/src/signplus/models/list_webhooks_response.py b/src/signplus/models/list_webhooks_response.py index 86689f1..7fefc42 100644 --- a/src/signplus/models/list_webhooks_response.py +++ b/src/signplus/models/list_webhooks_response.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .webhook import Webhook -@JsonMap({}) class ListWebhooksResponse(BaseModel): """ListWebhooksResponse @@ -14,12 +13,4 @@ class ListWebhooksResponse(BaseModel): :type webhooks: List[Webhook], optional """ - def __init__(self, webhooks: List[Webhook] = SENTINEL, **kwargs): - """ListWebhooksResponse - - :param webhooks: webhooks, defaults to None - :type webhooks: List[Webhook], optional - """ - if webhooks is not SENTINEL: - self.webhooks = self._define_list(webhooks, Webhook) - self._kwargs = kwargs + webhooks: Optional[List[Webhook]] = Field(default=None) diff --git a/src/signplus/models/page.py b/src/signplus/models/page.py index 774de24..5154f63 100644 --- a/src/signplus/models/page.py +++ b/src/signplus/models/page.py @@ -1,9 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL -@JsonMap({}) class Page(BaseModel): """Page @@ -13,16 +12,9 @@ class Page(BaseModel): :type height: int, optional """ - def __init__(self, width: int = SENTINEL, height: int = SENTINEL, **kwargs): - """Page - - :param width: Width of the page in pixels, defaults to None - :type width: int, optional - :param height: Height of the page in pixels, defaults to None - :type height: int, optional - """ - if width is not SENTINEL: - self.width = width - if height is not SENTINEL: - self.height = height - self._kwargs = kwargs + width: Optional[int] = Field( + default=None, description="Width of the page in pixels" + ) + height: Optional[int] = Field( + default=None, description="Height of the page in pixels" + ) diff --git a/src/signplus/models/recipient.py b/src/signplus/models/recipient.py index 846944d..f802e0e 100644 --- a/src/signplus/models/recipient.py +++ b/src/signplus/models/recipient.py @@ -1,12 +1,11 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .recipient_role import RecipientRole from .recipient_verification import RecipientVerification -@JsonMap({"id_": "id"}) class Recipient(BaseModel): """Recipient @@ -24,38 +23,19 @@ class Recipient(BaseModel): :type verification: RecipientVerification, optional """ - def __init__( - self, - name: str, - email: str, - role: RecipientRole, - id_: str = SENTINEL, - uid: str = SENTINEL, - verification: RecipientVerification = SENTINEL, - **kwargs, - ): - """Recipient - - :param id_: Unique identifier of the recipient, defaults to None - :type id_: str, optional - :param uid: Unique identifier of the user associated with the recipient, defaults to None - :type uid: str, optional - :param name: Name of the recipient - :type name: str - :param email: Email of the recipient - :type email: str - :param role: Role of the recipient (SIGNER signs the document, RECEIVES_COPY receives a copy of the document, IN_PERSON_SIGNER signs the document in person, SENDER sends the document) - :type role: RecipientRole - :param verification: verification, defaults to None - :type verification: RecipientVerification, optional - """ - if id_ is not SENTINEL: - self.id_ = id_ - if uid is not SENTINEL: - self.uid = uid - self.name = name - self.email = email - self.role = self._enum_matching(role, RecipientRole.list(), "role") - if verification is not SENTINEL: - self.verification = self._define_object(verification, RecipientVerification) - self._kwargs = kwargs + id_: Optional[str] = Field( + alias="id", + serialization_alias="id", + default=None, + description="Unique identifier of the recipient", + ) + uid: Optional[str] = Field( + default=None, + description="Unique identifier of the user associated with the recipient", + ) + name: str = Field(description="Name of the recipient") + email: str = Field(description="Email of the recipient") + role: RecipientRole = Field( + description="Role of the recipient (SIGNER signs the document, RECEIVES_COPY receives a copy of the document, IN_PERSON_SIGNER signs the document in person, SENDER sends the document)" + ) + verification: Optional[RecipientVerification] = Field(default=None) diff --git a/src/signplus/models/recipient_role.py b/src/signplus/models/recipient_role.py index 60e51f2..070b45f 100644 --- a/src/signplus/models/recipient_role.py +++ b/src/signplus/models/recipient_role.py @@ -1,7 +1,7 @@ from enum import Enum -class RecipientRole(Enum): +class RecipientRole(str, Enum): """An enumeration representing different categories. :cvar SIGNER: "SIGNER" @@ -16,10 +16,11 @@ class RecipientRole(Enum): RECEIVESCOPY = "RECEIVES_COPY" INPERSONSIGNER = "IN_PERSON_SIGNER" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list(map(lambda x: x.value, RecipientRole._member_map_.values())) diff --git a/src/signplus/models/recipient_verification.py b/src/signplus/models/recipient_verification.py index dfc5ebc..e141250 100644 --- a/src/signplus/models/recipient_verification.py +++ b/src/signplus/models/recipient_verification.py @@ -1,37 +1,26 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .recipient_verification_type import RecipientVerificationType -@JsonMap({"type_": "type"}) class RecipientVerification(BaseModel): """RecipientVerification - :param type_: Type of verification the recipient must complete before accessing the envelope. - `PASSCODE`: requires a code to be entered. - `SMS`: sends a code via SMS. - `ID_VERIFICATION`: prompts the recipient to complete an automated ID and selfie check., defaults to None + :param type_: Type of verification the recipient must complete before accessing the envelope. - `PASSCODE`: requires a code to be entered. - `SMS`: sends a code via SMS. - `ID_VERIFICATION`: prompts the recipient to complete an automated ID and selfie check., defaults to None :type type_: RecipientVerificationType, optional :param value: Required for `PASSCODE` and `SMS` verification. - `PASSCODE`: code required by the recipient to sign the document. - `SMS`: recipient's phone number. - `ID_VERIFICATION`: leave empty., defaults to None :type value: str, optional """ - def __init__( - self, - type_: RecipientVerificationType = SENTINEL, - value: str = SENTINEL, - **kwargs, - ): - """RecipientVerification - - :param type_: Type of verification the recipient must complete before accessing the envelope. - `PASSCODE`: requires a code to be entered. - `SMS`: sends a code via SMS. - `ID_VERIFICATION`: prompts the recipient to complete an automated ID and selfie check., defaults to None - :type type_: RecipientVerificationType, optional - :param value: Required for `PASSCODE` and `SMS` verification. - `PASSCODE`: code required by the recipient to sign the document. - `SMS`: recipient's phone number. - `ID_VERIFICATION`: leave empty., defaults to None - :type value: str, optional - """ - if type_ is not SENTINEL: - self.type_ = self._enum_matching( - type_, RecipientVerificationType.list(), "type_" - ) - if value is not SENTINEL: - self.value = value - self._kwargs = kwargs + type_: Optional[RecipientVerificationType] = Field( + alias="type", + serialization_alias="type", + default=None, + description="Type of verification the recipient must complete before accessing the envelope. - `PASSCODE`: requires a code to be entered. - `SMS`: sends a code via SMS. - `ID_VERIFICATION`: prompts the recipient to complete an automated ID and selfie check.", + ) + value: Optional[str] = Field( + default=None, + description="Required for `PASSCODE` and `SMS` verification. - `PASSCODE`: code required by the recipient to sign the document. - `SMS`: recipient's phone number. - `ID_VERIFICATION`: leave empty.", + ) diff --git a/src/signplus/models/recipient_verification_type.py b/src/signplus/models/recipient_verification_type.py index 6c11b3e..e0f0ff2 100644 --- a/src/signplus/models/recipient_verification_type.py +++ b/src/signplus/models/recipient_verification_type.py @@ -1,7 +1,7 @@ from enum import Enum -class RecipientVerificationType(Enum): +class RecipientVerificationType(str, Enum): """An enumeration representing different categories. :cvar SMS: "SMS" @@ -16,10 +16,11 @@ class RecipientVerificationType(Enum): PASSCODE = "PASSCODE" IDVERIFICATION = "ID_VERIFICATION" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list( diff --git a/src/signplus/models/rename_envelope_request.py b/src/signplus/models/rename_envelope_request.py index 958becd..f04b478 100644 --- a/src/signplus/models/rename_envelope_request.py +++ b/src/signplus/models/rename_envelope_request.py @@ -1,9 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL -@JsonMap({}) class RenameEnvelopeRequest(BaseModel): """RenameEnvelopeRequest @@ -11,12 +10,4 @@ class RenameEnvelopeRequest(BaseModel): :type name: str, optional """ - def __init__(self, name: str = SENTINEL, **kwargs): - """RenameEnvelopeRequest - - :param name: Name of the envelope, defaults to None - :type name: str, optional - """ - if name is not SENTINEL: - self.name = name - self._kwargs = kwargs + name: Optional[str] = Field(default=None, description="Name of the envelope") diff --git a/src/signplus/models/rename_template_request.py b/src/signplus/models/rename_template_request.py index 7bcbddc..d5ab8f7 100644 --- a/src/signplus/models/rename_template_request.py +++ b/src/signplus/models/rename_template_request.py @@ -1,8 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -@JsonMap({}) class RenameTemplateRequest(BaseModel): """RenameTemplateRequest @@ -10,11 +10,4 @@ class RenameTemplateRequest(BaseModel): :type name: str """ - def __init__(self, name: str, **kwargs): - """RenameTemplateRequest - - :param name: Name of the template - :type name: str - """ - self.name = name - self._kwargs = kwargs + name: str = Field(description="Name of the template") diff --git a/src/signplus/models/set_envelope_attachments_placeholders_request.py b/src/signplus/models/set_envelope_attachments_placeholders_request.py index 0a87ec7..6bc2976 100644 --- a/src/signplus/models/set_envelope_attachments_placeholders_request.py +++ b/src/signplus/models/set_envelope_attachments_placeholders_request.py @@ -1,11 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel from .attachment_placeholder_request import AttachmentPlaceholderRequest -@JsonMap({}) class SetEnvelopeAttachmentsPlaceholdersRequest(BaseModel): """SetEnvelopeAttachmentsPlaceholdersRequest @@ -13,13 +13,4 @@ class SetEnvelopeAttachmentsPlaceholdersRequest(BaseModel): :type placeholders: List[AttachmentPlaceholderRequest] """ - def __init__(self, placeholders: List[AttachmentPlaceholderRequest], **kwargs): - """SetEnvelopeAttachmentsPlaceholdersRequest - - :param placeholders: placeholders - :type placeholders: List[AttachmentPlaceholderRequest] - """ - self.placeholders = self._define_list( - placeholders, AttachmentPlaceholderRequest - ) - self._kwargs = kwargs + placeholders: List[AttachmentPlaceholderRequest] diff --git a/src/signplus/models/set_envelope_attachments_settings_request.py b/src/signplus/models/set_envelope_attachments_settings_request.py index b1fe63b..393d51a 100644 --- a/src/signplus/models/set_envelope_attachments_settings_request.py +++ b/src/signplus/models/set_envelope_attachments_settings_request.py @@ -1,10 +1,10 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel from .attachment_settings import AttachmentSettings -@JsonMap({}) class SetEnvelopeAttachmentsSettingsRequest(BaseModel): """SetEnvelopeAttachmentsSettingsRequest @@ -12,11 +12,4 @@ class SetEnvelopeAttachmentsSettingsRequest(BaseModel): :type settings: AttachmentSettings """ - def __init__(self, settings: AttachmentSettings, **kwargs): - """SetEnvelopeAttachmentsSettingsRequest - - :param settings: settings - :type settings: AttachmentSettings - """ - self.settings = self._define_object(settings, AttachmentSettings) - self._kwargs = kwargs + settings: AttachmentSettings diff --git a/src/signplus/models/set_envelope_comment_request.py b/src/signplus/models/set_envelope_comment_request.py index c46dbb2..33d8ddd 100644 --- a/src/signplus/models/set_envelope_comment_request.py +++ b/src/signplus/models/set_envelope_comment_request.py @@ -1,8 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -@JsonMap({}) class SetEnvelopeCommentRequest(BaseModel): """SetEnvelopeCommentRequest @@ -10,11 +10,4 @@ class SetEnvelopeCommentRequest(BaseModel): :type comment: str """ - def __init__(self, comment: str, **kwargs): - """SetEnvelopeCommentRequest - - :param comment: Comment for the envelope - :type comment: str - """ - self.comment = comment - self._kwargs = kwargs + comment: str = Field(description="Comment for the envelope") diff --git a/src/signplus/models/set_envelope_dynamic_fields_request.py b/src/signplus/models/set_envelope_dynamic_fields_request.py index c407b52..86558dd 100644 --- a/src/signplus/models/set_envelope_dynamic_fields_request.py +++ b/src/signplus/models/set_envelope_dynamic_fields_request.py @@ -1,11 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel from .dynamic_field import DynamicField -@JsonMap({}) class SetEnvelopeDynamicFieldsRequest(BaseModel): """SetEnvelopeDynamicFieldsRequest @@ -13,11 +13,4 @@ class SetEnvelopeDynamicFieldsRequest(BaseModel): :type dynamic_fields: List[DynamicField] """ - def __init__(self, dynamic_fields: List[DynamicField], **kwargs): - """SetEnvelopeDynamicFieldsRequest - - :param dynamic_fields: List of dynamic fields - :type dynamic_fields: List[DynamicField] - """ - self.dynamic_fields = self._define_list(dynamic_fields, DynamicField) - self._kwargs = kwargs + dynamic_fields: List[DynamicField] = Field(description="List of dynamic fields") diff --git a/src/signplus/models/set_envelope_expiration_request.py b/src/signplus/models/set_envelope_expiration_request.py index aaf01d5..0110e1e 100644 --- a/src/signplus/models/set_envelope_expiration_request.py +++ b/src/signplus/models/set_envelope_expiration_request.py @@ -1,8 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -@JsonMap({}) class SetEnvelopeExpirationRequest(BaseModel): """SetEnvelopeExpirationRequest @@ -10,11 +10,4 @@ class SetEnvelopeExpirationRequest(BaseModel): :type expires_at: int """ - def __init__(self, expires_at: int, **kwargs): - """SetEnvelopeExpirationRequest - - :param expires_at: Unix timestamp of the expiration date - :type expires_at: int - """ - self.expires_at = expires_at - self._kwargs = kwargs + expires_at: int = Field(description="Unix timestamp of the expiration date") diff --git a/src/signplus/models/set_envelope_legality_level_request.py b/src/signplus/models/set_envelope_legality_level_request.py index 409e94b..0141bcf 100644 --- a/src/signplus/models/set_envelope_legality_level_request.py +++ b/src/signplus/models/set_envelope_legality_level_request.py @@ -1,11 +1,10 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .envelope_legality_level import EnvelopeLegalityLevel -@JsonMap({}) class SetEnvelopeLegalityLevelRequest(BaseModel): """SetEnvelopeLegalityLevelRequest @@ -13,14 +12,7 @@ class SetEnvelopeLegalityLevelRequest(BaseModel): :type legality_level: EnvelopeLegalityLevel, optional """ - def __init__(self, legality_level: EnvelopeLegalityLevel = SENTINEL, **kwargs): - """SetEnvelopeLegalityLevelRequest - - :param legality_level: Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes), defaults to None - :type legality_level: EnvelopeLegalityLevel, optional - """ - if legality_level is not SENTINEL: - self.legality_level = self._enum_matching( - legality_level, EnvelopeLegalityLevel.list(), "legality_level" - ) - self._kwargs = kwargs + legality_level: Optional[EnvelopeLegalityLevel] = Field( + default=None, + description="Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes)", + ) diff --git a/src/signplus/models/set_template_comment_request.py b/src/signplus/models/set_template_comment_request.py index a7d0b99..0969b0f 100644 --- a/src/signplus/models/set_template_comment_request.py +++ b/src/signplus/models/set_template_comment_request.py @@ -1,8 +1,8 @@ -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -@JsonMap({}) class SetTemplateCommentRequest(BaseModel): """SetTemplateCommentRequest @@ -10,11 +10,4 @@ class SetTemplateCommentRequest(BaseModel): :type comment: str """ - def __init__(self, comment: str, **kwargs): - """SetTemplateCommentRequest - - :param comment: Comment for the template - :type comment: str - """ - self.comment = comment - self._kwargs = kwargs + comment: str = Field(description="Comment for the template") diff --git a/src/signplus/models/signing_step.py b/src/signplus/models/signing_step.py index 4b507ca..1a875d8 100644 --- a/src/signplus/models/signing_step.py +++ b/src/signplus/models/signing_step.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .recipient import Recipient -@JsonMap({}) class SigningStep(BaseModel): """SigningStep @@ -14,12 +13,6 @@ class SigningStep(BaseModel): :type recipients: List[Recipient], optional """ - def __init__(self, recipients: List[Recipient] = SENTINEL, **kwargs): - """SigningStep - - :param recipients: List of recipients, defaults to None - :type recipients: List[Recipient], optional - """ - if recipients is not SENTINEL: - self.recipients = self._define_list(recipients, Recipient) - self._kwargs = kwargs + recipients: Optional[List[Recipient]] = Field( + default=None, description="List of recipients" + ) diff --git a/src/signplus/models/template.py b/src/signplus/models/template.py index 2329b01..0be44d2 100644 --- a/src/signplus/models/template.py +++ b/src/signplus/models/template.py @@ -1,8 +1,8 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .envelope_legality_level import EnvelopeLegalityLevel from .template_signing_step import TemplateSigningStep from .document import Document @@ -10,7 +10,6 @@ from .envelope_attachments import EnvelopeAttachments -@JsonMap({"id_": "id"}) class Template(BaseModel): """Template @@ -44,83 +43,38 @@ class Template(BaseModel): :type attachments: EnvelopeAttachments, optional """ - def __init__( - self, - id_: str = SENTINEL, - name: str = SENTINEL, - comment: str = SENTINEL, - pages: int = SENTINEL, - legality_level: EnvelopeLegalityLevel = SENTINEL, - created_at: int = SENTINEL, - updated_at: int = SENTINEL, - expiration_delay: int = SENTINEL, - num_recipients: int = SENTINEL, - signing_steps: List[TemplateSigningStep] = SENTINEL, - documents: List[Document] = SENTINEL, - notification: EnvelopeNotification = SENTINEL, - dynamic_fields: List[str] = SENTINEL, - attachments: EnvelopeAttachments = SENTINEL, - **kwargs, - ): - """Template - - :param id_: Unique identifier of the template, defaults to None - :type id_: str, optional - :param name: Name of the template, defaults to None - :type name: str, optional - :param comment: Comment for the template, defaults to None - :type comment: str, optional - :param pages: Total number of pages in the template, defaults to None - :type pages: int, optional - :param legality_level: Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes), defaults to None - :type legality_level: EnvelopeLegalityLevel, optional - :param created_at: Unix timestamp of the creation date, defaults to None - :type created_at: int, optional - :param updated_at: Unix timestamp of the last modification date, defaults to None - :type updated_at: int, optional - :param expiration_delay: Expiration delay added to the current time when an envelope is created from this template, defaults to None - :type expiration_delay: int, optional - :param num_recipients: Number of recipients in the envelope, defaults to None - :type num_recipients: int, optional - :param signing_steps: signing_steps, defaults to None - :type signing_steps: List[TemplateSigningStep], optional - :param documents: documents, defaults to None - :type documents: List[Document], optional - :param notification: notification, defaults to None - :type notification: EnvelopeNotification, optional - :param dynamic_fields: List of dynamic fields, defaults to None - :type dynamic_fields: List[str], optional - :param attachments: attachments, defaults to None - :type attachments: EnvelopeAttachments, optional - """ - if id_ is not SENTINEL: - self.id_ = id_ - if name is not SENTINEL: - self.name = name - if comment is not SENTINEL: - self.comment = comment - if pages is not SENTINEL: - self.pages = pages - if legality_level is not SENTINEL: - self.legality_level = self._enum_matching( - legality_level, EnvelopeLegalityLevel.list(), "legality_level" - ) - if created_at is not SENTINEL: - self.created_at = created_at - if updated_at is not SENTINEL: - self.updated_at = updated_at - if expiration_delay is not SENTINEL: - self.expiration_delay = expiration_delay - if num_recipients is not SENTINEL: - self.num_recipients = num_recipients - if signing_steps is not SENTINEL: - self.signing_steps = self._define_list(signing_steps, TemplateSigningStep) - if documents is not SENTINEL: - self.documents = self._define_list(documents, Document) - if notification is not SENTINEL: - self.notification = self._define_object(notification, EnvelopeNotification) - if dynamic_fields is not SENTINEL: - self.dynamic_fields = dynamic_fields - if attachments is not SENTINEL: - self.attachments = self._define_object(attachments, EnvelopeAttachments) - self._kwargs = kwargs + id_: Optional[str] = Field( + alias="id", + serialization_alias="id", + default=None, + description="Unique identifier of the template", + ) + name: Optional[str] = Field(default=None, description="Name of the template") + comment: Optional[str] = Field(default=None, description="Comment for the template") + pages: Optional[int] = Field( + default=None, description="Total number of pages in the template" + ) + legality_level: Optional[EnvelopeLegalityLevel] = Field( + default=None, + description="Legal level of the envelope (SES is Simple Electronic Signature, QES_EIDAS is Qualified Electronic Signature, QES_ZERTES is Qualified Electronic Signature with Zertes)", + ) + created_at: Optional[int] = Field( + default=None, description="Unix timestamp of the creation date" + ) + updated_at: Optional[int] = Field( + default=None, description="Unix timestamp of the last modification date" + ) + expiration_delay: Optional[int] = Field( + default=None, + description="Expiration delay added to the current time when an envelope is created from this template", + ) + num_recipients: Optional[int] = Field( + default=None, description="Number of recipients in the envelope" + ) + signing_steps: Optional[List[TemplateSigningStep]] = Field(default=None) + documents: Optional[List[Document]] = Field(default=None) + notification: Optional[EnvelopeNotification] = Field(default=None) + dynamic_fields: Optional[List[str]] = Field( + default=None, description="List of dynamic fields" + ) + attachments: Optional[EnvelopeAttachments] = Field(default=None) diff --git a/src/signplus/models/template_order_field.py b/src/signplus/models/template_order_field.py index cf99eb0..38d3934 100644 --- a/src/signplus/models/template_order_field.py +++ b/src/signplus/models/template_order_field.py @@ -1,7 +1,7 @@ from enum import Enum -class TemplateOrderField(Enum): +class TemplateOrderField(str, Enum): """An enumeration representing different categories. :cvar TEMPLATEID: "TEMPLATE_ID" @@ -19,10 +19,11 @@ class TemplateOrderField(Enum): TEMPLATEMODIFICATIONDATE = "TEMPLATE_MODIFICATION_DATE" TEMPLATENAME = "TEMPLATE_NAME" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list(map(lambda x: x.value, TemplateOrderField._member_map_.values())) diff --git a/src/signplus/models/template_recipient.py b/src/signplus/models/template_recipient.py index 541fb0d..93be561 100644 --- a/src/signplus/models/template_recipient.py +++ b/src/signplus/models/template_recipient.py @@ -1,11 +1,10 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .template_recipient_role import TemplateRecipientRole -@JsonMap({"id_": "id"}) class TemplateRecipient(BaseModel): """TemplateRecipient @@ -21,36 +20,19 @@ class TemplateRecipient(BaseModel): :type role: TemplateRecipientRole, optional """ - def __init__( - self, - id_: str = SENTINEL, - uid: str = SENTINEL, - name: str = SENTINEL, - email: str = SENTINEL, - role: TemplateRecipientRole = SENTINEL, - **kwargs, - ): - """TemplateRecipient - - :param id_: Unique identifier of the recipient, defaults to None - :type id_: str, optional - :param uid: Unique identifier of the user associated with the recipient, defaults to None - :type uid: str, optional - :param name: Name of the recipient, defaults to None - :type name: str, optional - :param email: Email of the recipient, defaults to None - :type email: str, optional - :param role: Role of the recipient (SIGNER signs the document, RECEIVES_COPY receives a copy of the document, IN_PERSON_SIGNER signs the document in person, SENDER sends the document), defaults to None - :type role: TemplateRecipientRole, optional - """ - if id_ is not SENTINEL: - self.id_ = id_ - if uid is not SENTINEL: - self.uid = uid - if name is not SENTINEL: - self.name = name - if email is not SENTINEL: - self.email = email - if role is not SENTINEL: - self.role = self._enum_matching(role, TemplateRecipientRole.list(), "role") - self._kwargs = kwargs + id_: Optional[str] = Field( + alias="id", + serialization_alias="id", + default=None, + description="Unique identifier of the recipient", + ) + uid: Optional[str] = Field( + default=None, + description="Unique identifier of the user associated with the recipient", + ) + name: Optional[str] = Field(default=None, description="Name of the recipient") + email: Optional[str] = Field(default=None, description="Email of the recipient") + role: Optional[TemplateRecipientRole] = Field( + default=None, + description="Role of the recipient (SIGNER signs the document, RECEIVES_COPY receives a copy of the document, IN_PERSON_SIGNER signs the document in person, SENDER sends the document)", + ) diff --git a/src/signplus/models/template_recipient_role.py b/src/signplus/models/template_recipient_role.py index dea216c..758d711 100644 --- a/src/signplus/models/template_recipient_role.py +++ b/src/signplus/models/template_recipient_role.py @@ -1,7 +1,7 @@ from enum import Enum -class TemplateRecipientRole(Enum): +class TemplateRecipientRole(str, Enum): """An enumeration representing different categories. :cvar SIGNER: "SIGNER" @@ -19,10 +19,11 @@ class TemplateRecipientRole(Enum): INPERSONSIGNER = "IN_PERSON_SIGNER" SENDER = "SENDER" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list(map(lambda x: x.value, TemplateRecipientRole._member_map_.values())) diff --git a/src/signplus/models/template_signing_step.py b/src/signplus/models/template_signing_step.py index 3b414f4..e9f2468 100644 --- a/src/signplus/models/template_signing_step.py +++ b/src/signplus/models/template_signing_step.py @@ -1,12 +1,11 @@ from __future__ import annotations from typing import List -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .template_recipient import TemplateRecipient -@JsonMap({}) class TemplateSigningStep(BaseModel): """TemplateSigningStep @@ -14,12 +13,6 @@ class TemplateSigningStep(BaseModel): :type recipients: List[TemplateRecipient], optional """ - def __init__(self, recipients: List[TemplateRecipient] = SENTINEL, **kwargs): - """TemplateSigningStep - - :param recipients: List of recipients, defaults to None - :type recipients: List[TemplateRecipient], optional - """ - if recipients is not SENTINEL: - self.recipients = self._define_list(recipients, TemplateRecipient) - self._kwargs = kwargs + recipients: Optional[List[TemplateRecipient]] = Field( + default=None, description="List of recipients" + ) diff --git a/src/signplus/models/utils/base_error.py b/src/signplus/models/utils/base_error.py new file mode 100644 index 0000000..ef59699 --- /dev/null +++ b/src/signplus/models/utils/base_error.py @@ -0,0 +1,116 @@ +from typing import Any, Dict, Optional, Type +from pydantic import BaseModel as PydanticBaseModel, ValidationError + + +class BaseError(Exception): + """ + Base exception class for SDK error models. + + Combines Exception behavior with Pydantic validation: + - Can be raised as an exception + - Validates input data using Pydantic + - Provides attribute access to error fields + - Includes status and response for HTTP errors + """ + + # Pydantic model class for validation (overridden by subclasses) + _model_class: Type[PydanticBaseModel] = None + + def __init__(self, **data: Any): + """ + Initialize error with validated data. + + :param data: Error data to validate + """ + # If _model_class is set, use it for validation + if self._model_class is not None: + try: + # Validate data using Pydantic model + validated_data = self._model_class(**data) + # Store validated fields as instance attributes + for field_name in self._model_class.model_fields: + setattr(self, field_name, getattr(validated_data, field_name)) + # Store the validated model for serialization + self._data = validated_data + except ValidationError: + # If validation fails, store raw data + for key, value in data.items(): + setattr(self, key, value) + self._data = data + else: + # No validation - just store attributes + for key, value in data.items(): + setattr(self, key, value) + self._data = data + + # Add standard error attributes + self.status: Optional[int] = getattr(self, "status", None) + self.response: Optional[Any] = getattr(self, "response", None) + + # Call Exception.__init__ with message if available + message = getattr(self, "message", str(data)) + super().__init__(message) + + def model_dump_original(self, **kwargs: Any) -> Dict[str, Any]: + """ + Serialize error using original field names. + + :param kwargs: Additional arguments for serialization + :return: Dictionary with original API field names + :rtype: Dict[str, Any] + """ + if isinstance(self._data, PydanticBaseModel): + # Set exclude_unset=True by default + if "exclude_unset" not in kwargs: + kwargs["exclude_unset"] = True + return self._data.model_dump(by_alias=True, **kwargs) + else: + # Raw data + return self._data if isinstance(self._data, dict) else {} + + def _map(self, **kwargs: Any) -> Dict[str, Any]: + """ + Legacy alias for model_dump_original(). + + :param kwargs: Additional arguments + :return: Dictionary with original field names + :rtype: Dict[str, Any] + """ + return self.model_dump_original(**kwargs) + + @classmethod + def _unmap(cls, obj: Any) -> "BaseError": + """ + Create error instance from dictionary. + + :param obj: Dictionary or object to convert + :return: Error instance + :rtype: BaseError + """ + if isinstance(obj, dict): + return cls(**obj) + return obj + + @property + def _kwargs(self) -> Dict[str, Any]: + """ + Access extra fields not in schema. + + :return: Dictionary of extra fields + :rtype: Dict[str, Any] + """ + if isinstance(self._data, PydanticBaseModel): + return getattr(self._data, "__pydantic_extra__", {}) + return {} + + def __str__(self) -> str: + """String representation of the error.""" + message = getattr(self, "message", None) + status = getattr(self, "status", None) + if message and status: + return f"{status}: {message}" + elif message: + return str(message) + elif status: + return f"Error {status}" + return super().__str__() diff --git a/src/signplus/models/utils/base_model.py b/src/signplus/models/utils/base_model.py index 48c34e9..4bd6616 100644 --- a/src/signplus/models/utils/base_model.py +++ b/src/signplus/models/utils/base_model.py @@ -1,310 +1,120 @@ -import re -import operator -from typing import List, Union, Type, Any, TypeVar, Optional -from enum import Enum -from .one_of_base_model import OneOfBaseModel -from .sentinel import SENTINEL +from pydantic import BaseModel as PydanticBaseModel, ConfigDict, ValidationError +from typing import Any, Dict -T = TypeVar("T") - -class BaseModel: - """ - A base class that most of the models in the SDK inherited from. +class BaseModel(PydanticBaseModel): """ + Pydantic-based model for SDK objects with custom configuration. - def __init__(self): - pass - - def _define_object(self, input_data: Any, input_class: Type[T]) -> Optional[T]: - """ - Check if the input data is an instance of the input class and return the input data if it is. - Otherwise, return an instance of the input class. - - :param input_data: The input data to be checked. - :param input_class: The class that the input data should be an instance of. - :return: The input data if it is an instance of input_class, otherwise an instance of input_class. - :rtype: object - """ - if input_data is None or input_data is SENTINEL: - return None - elif isinstance(input_data, input_class): - return input_data - else: - return input_class._unmap(input_data) - - def _define_list( - self, input_data: Optional[List[Any]], list_class: Type[T] - ) -> Optional[List[T]]: - """ - Create a list of instances of a specified class from input data. - :param input_data: The input data to be transformed into a list of instances. - :param list_class: The class that each instance in the list should be an instance of. - :return: A list of instances of list_class. - :rtype: list - """ + This class extends Pydantic's BaseModel to provide: + - Automatic validation on instantiation + - Type-safe attribute access + - JSON serialization with API field name mapping + - Support for additional properties (extra fields) + """ - if input_data is None or input_data is SENTINEL: - return None + model_config = ConfigDict( + # Allow extra fields beyond defined properties (replaces **kwargs behavior) + extra="allow", + # Validate field values when they are assigned after initialization + validate_assignment=True, + # Use enum values instead of enum objects in serialization + use_enum_values=True, + # Allow models to be populated using either field name or alias + populate_by_name=True, + # Arbitrary types allowed (for flexibility with custom types) + arbitrary_types_allowed=False, + ) + + def model_dump_original(self, **kwargs: Any) -> Dict[str, Any]: + """ + Serialize model using original field names from OpenAPI spec. + + This ensures JSON output matches the API contract by using field aliases + (typically camelCase) instead of Python field names (snake_case). + + By default, unset fields are excluded from the output. + To include them, pass exclude_unset=False explicitly. + + :param kwargs: Additional arguments passed to model_dump() + :return: Dictionary with original API field names + :rtype: Dict[str, Any] + + Example: + >>> cat = Cat(body_fat_percentage=15.5, age=None) + >>> cat.model_dump_original() + {'bodyFatPercentage': 15.5, 'age': None} + >>> cat.model_dump_original(exclude_unset=False) + {'bodyFatPercentage': 15.5, 'age': None} + """ + # Set exclude_unset=True by default to exclude fields that were not explicitly set + # Note: We do NOT exclude None values by default, because if a field is explicitly + # set to None, it should be sent as null in the JSON to the API + if "exclude_unset" not in kwargs: + kwargs["exclude_unset"] = True + + # Exclude extra fields by default (additional properties not in schema) + # This matches the expected behavior where undefined fields are not sent to APIs + result = self.model_dump(by_alias=True, **kwargs) + + # Remove extra fields from the result + extra_fields = getattr(self, "__pydantic_extra__", {}) + if extra_fields: + for extra_field_name in extra_fields.keys(): + result.pop(extra_field_name, None) - result: List[T] = [] - for item in input_data: - if hasattr(list_class, "__args__") and len(list_class.__args__) > 0: - class_list = self.__create_class_map(list_class) - OneOfBaseModel.class_list = class_list - result.append(OneOfBaseModel.return_one_of(item)) - elif issubclass(list_class, Enum): - result.append( - self._enum_matching(item, list_class.list(), list_class.__name__) - ) - elif isinstance(item, list_class): - result.append(item) - elif isinstance(item, dict): - result.append(list_class._unmap(item)) - else: - result.append(list_class(item)) return result - def _define_str( - self, - variable_name: str, - value: Optional[Any], - nullable=False, - pattern: Optional[str] = None, - min_length: Optional[int] = None, - max_length: Optional[int] = None, - ) -> Optional[str]: - """ - Check if a string value is within the specified boundaries and matches a regex pattern. - Return the value if it is, otherwise raise a ValueError. - - :param variable_name: The variable name. - :type variable_name: str - :param value: The value to be checked. - :type value: str - :param nullable: Whether the value can be None. - :type nullable: bool - :param pattern: The regex pattern to match. - :type pattern: str - :param min_length: The minimum length of the value. - :type min_length: int - :param max_length: The maximum length of the value. - :type max_length: int - :param inclusive_lenght_boundary: Whether the length boundaries are inclusive. - :type inclusive_lenght_boundary: bool - - :raises ValueError: If the value is not within the boundaries or does not match the pattern. - - :return: The value if it is within the boundaries and matches the pattern. - :rtype: str - """ - if value is None and not nullable: - raise ValueError(f"{variable_name} cannot be null.") - if value is None or value is SENTINEL: - return None - - if pattern: - self._pattern_matching(value, pattern, variable_name) - - if min_length is not None: - operation = operator.ge - self._boundary_check(variable_name, len(value), min_length, operation, str) - - if max_length is not None: - operation = operator.le - self._boundary_check(variable_name, len(value), max_length, operation, str) - - return value - - def _define_number( - self, - variable_name: str, - value: Optional[Union[float, int]], - nullable=False, - ge: Optional[Union[float, int]] = None, - gt: Optional[Union[float, int]] = None, - le: Optional[Union[float, int]] = None, - lt: Optional[Union[float, int]] = None, - ) -> Optional[Union[float, int]]: - """ - Check if a number value is within the specified boundaries. - Return the value if it is, otherwise raise a ValueError. - - :param variable_name: The variable name. - :type variable_name: str - :param value: The value to be checked. - :type value: Union[float, int] - :param nullable: Whether the value can be None. - :type nullable: bool - :param ge: The minimum value of the number (inclusive). The value must be greater than or equal to this. - :type ge: Union[float, int] - :param gt: The minimum value of the number (exclusive). The value must be greater than this. - :type gt: Union[float, int] - :param le: The maximum value of the number (inclusive). The value must be less than or equal to this. - :type le: Union[float, int] - :param lt: The maximum value of the number (exclusive). The value must be less than this. - :type lt: Union[float, int] - - :raises ValueError: If the value is not within the boundaries. - - :return: The value if it is within the boundaries. - :rtype: Union[float, int] + @classmethod + def model_validate_original(cls, obj: Any) -> "BaseModel": """ - if value is None and not nullable: - raise ValueError(f"{variable_name} cannot be null.") - - if value is None or value is SENTINEL: - return None - - if ge is not None: - operation = operator.ge - self._boundary_check(variable_name, value, ge, operation, float) - - if gt is not None: - operation = operator.gt - self._boundary_check(variable_name, value, gt, operation, float) + Parse and validate object using original field names from OpenAPI spec. - if le is not None: - operation = operator.le - self._boundary_check(variable_name, value, le, operation, float) + This method accepts data with API field names (aliases) and creates + a validated model instance. - if lt is not None: - operation = operator.lt - self._boundary_check(variable_name, value, lt, operation, float) + :param obj: Dictionary or object to validate + :return: Validated model instance + :rtype: BaseModel - return value - - def _boundary_check( - self, - variable_name: str, - value: float, - boundary: float, - operation: operator, - value_type: Union[str, float, int], - ) -> Optional[str]: + Example: + >>> data = {'bodyFatPercentage': 15.5} + >>> cat = Cat.model_validate_original(data) + >>> cat.body_fat_percentage + 15.5 """ - Checks if a value is within the specified boundaries and returns the value if it is. - - :param variable_name: The variable name. - :type variable_name: str - :param value: The value to be checked. - :type value: Union[str, float, int] - :param boundary: The boundary value to be checked against. - :type boundary: float - :param operator: The operator to be used for the boundary check. - :type operator: operator - :param type: The type of the value. - :type type: Union[str, float, int] - - :raises ValueError: If the value is not within the boundaries. + return cls.model_validate(obj) - :return: The value if it is within the boundaries. - :rtype: Union[str, float, int] + def _map(self, **kwargs: Any) -> Dict[str, Any]: """ - reference = "length" if value_type is str else "value" - if not operation(value, boundary): - raise ValueError( - f"Invalid {reference} for {variable_name}: must satisfy the condition {operation.__name__} {boundary}, received {value}" - ) + Legacy alias for model_dump_original() for backward compatibility. - return value - - def _pattern_matching( - self, value: Optional[str], pattern: str, variable_name: str - ) -> Optional[str]: + :param kwargs: Additional arguments passed to model_dump_original() + :return: Dictionary with original API field names + :rtype: Dict[str, Any] """ - Checks if a value matches a regex pattern and returns the value if there's a match. + return self.model_dump_original(**kwargs) - :param value: The value to be checked. - :type value: str - :param pattern: The regex pattern. - :type pattern: str - :param variable_name: The variable name. - :type variable_name: str - :return: The value if it matches the pattern. - :rtype: str - :raises ValueError: If the value does not match the pattern. + @classmethod + def _unmap(cls, obj: Any) -> "BaseModel": """ - if value is None: - return None - - if re.match(r"{}".format(pattern), value): - return value - else: - raise ValueError( - f"Invalid value for {variable_name}: must match {pattern}, received {value}" - ) + Legacy alias for model_validate_original() for backward compatibility. - def _enum_matching( - self, value: Union[str, Enum], enum_values: List[str], variable_name: str - ) -> Union[str, Enum]: + :param obj: Dictionary or object to validate + :return: Validated model instance + :rtype: BaseModel """ - Checks if a value (str or enum) matches the required enum values and returns the value if there's a match. + return cls.model_validate_original(obj) - :param value: The value to be checked. - :type value: Union[str, Enum] - :param enum_values: The list of valid enum values. - :type enum_values: List[str] - :param variable_name: The variable name. - :type variable_name: str - :return: The value if it matches one of the enum values. - :rtype: Union[str, Enum] - :raises ValueError: If the value does not match any of the enum values. + @property + def _kwargs(self) -> Dict[str, Any]: """ - if value is None: - return None + Access extra fields (additional properties beyond defined schema). - str_value = value.value if isinstance(value, Enum) else value - if str_value in enum_values: - return value - else: - raise ValueError( - f"Invalid value for {variable_name}: must match one of {enum_values}, received {value}" - ) - - def _get_representation(self, level: int = 0) -> str: - """ - Get a string representation of the model. - - :param int level: The indentation level. - :return: A string representation of the model. - """ - indent = " " * level - representation_lines = [] - - for attr, value in vars(self).items(): - if value is not None: - value_representation = ( - value._get_representation(level + 1) - if hasattr(value, "_get_representation") - else repr(value) - ) - representation_lines.append( - f"{indent} {attr}={value_representation}" - ) - - return ( - f"{self.__class__.__name__}(\n" - + ",\n".join(representation_lines) - + f"\n{indent})" - ) - - def __str__(self): - return self._get_representation() - - def __repr__(self): - return self._get_representation() - - def __create_class_map(self, union_type): - """ - Create a dictionary that maps class names to the actual classes in a Union type. + In Pydantic v2, extra fields are stored in __pydantic_extra__. + This property provides backward compatibility with v1's **kwargs pattern. - :param union_type: The Union type to create a class map for. - :return: A dictionary mapping class names to classes. - :rtype: dict + :return: Dictionary of extra fields + :rtype: Dict[str, Any] """ - class_map = {} - for arg in union_type.__args__: - if arg.__name__: - class_map[arg.__name__] = arg - return class_map + return getattr(self, "__pydantic_extra__", {}) diff --git a/src/signplus/models/utils/cast_models.py b/src/signplus/models/utils/cast_models.py index 2ad2229..679566e 100644 --- a/src/signplus/models/utils/cast_models.py +++ b/src/signplus/models/utils/cast_models.py @@ -1,7 +1,8 @@ from enum import Enum -from typing import get_args, Union +from typing import Any, get_args, Union from inspect import isclass from .one_of_base_model import OneOfBaseModel +from pydantic import ValidationError def cast_models(func): @@ -23,7 +24,11 @@ def wrapper(self, *clss, **kwargs): new_cls_args.append(_get_instanced_type(input, input_type)) for type_name, input in kwargs.items(): - new_kwargs[type_name] = _get_instanced_type(input, cls_types[type_name]) + # Config parameters pass through unchanged - they're already dicts + if type_name == "request_config": + new_kwargs[type_name] = input + else: + new_kwargs[type_name] = _get_instanced_type(input, cls_types[type_name]) return func(self, *new_cls_args, **new_kwargs) @@ -35,6 +40,14 @@ def _get_instanced_type(data, input_type): :param input_type: The type of the input. :return: The instanced type. """ + # `typing.Any` means "no validation" — pass the data through + # unchanged. Without this guard, downstream branches eventually + # call `isinstance(data, Any)`, which raises + # `TypeError: typing.Any cannot be used with isinstance()` and + # crashes any method whose annotation propagates an Any-schema. + if input_type is Any: + return data + # Instanciate oneOf models if _is_one_of_model(input_type): class_list = { @@ -53,12 +66,35 @@ def _get_instanced_type(data, input_type): # Instanciate object models elif isinstance(data, dict) and input_type is not str: - return input_type(**data) + # Pydantic models: use model_validate() for better validation + if hasattr(input_type, "model_validate"): + try: + return input_type.model_validate(data) + except ValidationError as e: + # Convert ValidationError to TypeError for backward compatibility + raise TypeError(f"Invalid data for {input_type.__name__}: {e}") + # Legacy models or direct instantiation + else: + return input_type(**data) # Instanciate list of object models elif isinstance(data, list) and all(isinstance(i, dict) for i in data): element_type = get_args(input_type)[0] - return [element_type(**item) for item in data] + # `List[Any]` — no per-item validation, just return the list as-is. + # Otherwise the else-branch would call `Any(**item)` which raises + # `TypeError: Cannot instantiate typing.Any`. + if element_type is Any: + return data + # Pydantic models: use model_validate() for each item + if hasattr(element_type, "model_validate"): + try: + return [element_type.model_validate(item) for item in data] + except ValidationError as e: + # Convert ValidationError to TypeError for backward compatibility + raise TypeError(f"Invalid data for {element_type.__name__}: {e}") + # Legacy models or direct instantiation + else: + return [element_type(**item) for item in data] # Instanciate bytes if input is str elif input_type is bytes and isinstance(data, str): diff --git a/src/signplus/models/utils/one_of_base_model.py b/src/signplus/models/utils/one_of_base_model.py index 8186278..699e13d 100644 --- a/src/signplus/models/utils/one_of_base_model.py +++ b/src/signplus/models/utils/one_of_base_model.py @@ -68,6 +68,13 @@ def _get_instance(cls, class_constructor, input_data): :return: An instance of the class if the input data matches the class constructor or can be used to initialize the class, None otherwise. """ + # `Union[..., Any]` / `Optional[Any]` propagate `typing.Any` through + # `class_list`. `isinstance(..., Any)` raises, so short-circuit and + # pass the data through — `Any` in a oneOf means the branch accepts + # anything by definition. + if class_constructor is Any: + return input_data + # Check if the class is only a TypeHint. origin = get_origin(class_constructor) if origin is not None and isinstance(input_data, list): @@ -108,6 +115,11 @@ def _get_list_instance( inner_type = args[0] + # `List[Any]` inside a oneOf branch — every item satisfies it by + # definition, and `isinstance(item, Any)` would raise. + if inner_type is Any: + return input_data + if not all(isinstance(item, inner_type) for item in input_data): return [inner_type._unmap(item) for item in input_data] diff --git a/src/signplus/models/webhook.py b/src/signplus/models/webhook.py index 970c4d1..a8d404a 100644 --- a/src/signplus/models/webhook.py +++ b/src/signplus/models/webhook.py @@ -1,11 +1,10 @@ from __future__ import annotations -from .utils.json_map import JsonMap +from pydantic import Field +from typing import Optional from .utils.base_model import BaseModel -from .utils.sentinel import SENTINEL from .webhook_event import WebhookEvent -@JsonMap({"id_": "id"}) class Webhook(BaseModel): """Webhook @@ -17,26 +16,13 @@ class Webhook(BaseModel): :type target: str, optional """ - def __init__( - self, - id_: str = SENTINEL, - event: WebhookEvent = SENTINEL, - target: str = SENTINEL, - **kwargs, - ): - """Webhook - - :param id_: Unique identifier of the webhook, defaults to None - :type id_: str, optional - :param event: Event of the webhook, defaults to None - :type event: WebhookEvent, optional - :param target: Target URL of the webhook, defaults to None - :type target: str, optional - """ - if id_ is not SENTINEL: - self.id_ = id_ - if event is not SENTINEL: - self.event = self._enum_matching(event, WebhookEvent.list(), "event") - if target is not SENTINEL: - self.target = target - self._kwargs = kwargs + id_: Optional[str] = Field( + alias="id", + serialization_alias="id", + default=None, + description="Unique identifier of the webhook", + ) + event: Optional[WebhookEvent] = Field( + default=None, description="Event of the webhook" + ) + target: Optional[str] = Field(default=None, description="Target URL of the webhook") diff --git a/src/signplus/models/webhook_event.py b/src/signplus/models/webhook_event.py index bd337c8..e35ad1b 100644 --- a/src/signplus/models/webhook_event.py +++ b/src/signplus/models/webhook_event.py @@ -1,7 +1,7 @@ from enum import Enum -class WebhookEvent(Enum): +class WebhookEvent(str, Enum): """An enumeration representing different categories. :cvar ENVELOPEEXPIRED: "ENVELOPE_EXPIRED" @@ -22,10 +22,11 @@ class WebhookEvent(Enum): ENVELOPECOMPLETED = "ENVELOPE_COMPLETED" ENVELOPEAUDITTRAIL = "ENVELOPE_AUDIT_TRAIL" + @staticmethod def list(): - """Lists all category values. + """Lists all enum values. - :return: A list of all category values. + :return: A list of all enum values. :rtype: list """ return list(map(lambda x: x.value, WebhookEvent._member_map_.values())) diff --git a/src/signplus/net/headers/base_header.py b/src/signplus/net/headers/base_header.py index cc1eb3c..8c6b8c3 100644 --- a/src/signplus/net/headers/base_header.py +++ b/src/signplus/net/headers/base_header.py @@ -2,8 +2,25 @@ class BaseHeader: + """ + Base class for authentication header implementations. + Defines the interface for setting authentication values and retrieving HTTP headers. + """ + def set_value(self, value: Any) -> None: + """ + Set the authentication value. + Subclasses should override this method to store authentication credentials. + + :param value: The authentication value to set. + """ pass def get_headers(self) -> Dict[str, str]: + """ + Get the HTTP headers containing authentication information. + Subclasses should override this method to return appropriate authentication headers. + + :return: A dictionary of HTTP headers with authentication data. + """ pass diff --git a/src/signplus/net/request_chain/handlers/http_handler.py b/src/signplus/net/request_chain/handlers/http_handler.py index 6fc9255..5ac9289 100644 --- a/src/signplus/net/request_chain/handlers/http_handler.py +++ b/src/signplus/net/request_chain/handlers/http_handler.py @@ -2,6 +2,7 @@ from requests.exceptions import Timeout from typing import Generator, Optional, Tuple +from pydantic import TypeAdapter from .base_handler import BaseHandler from ...transport.request import Request from ...transport.response import Response @@ -36,11 +37,14 @@ def handle( try: request_args = self._get_request_data(request) + # Get timeout from config if available, otherwise use default + timeout = self._get_timeout_from_config(request) + result = requests.request( request.method, request.url, headers=request.headers, - timeout=self._timeout_in_seconds, + timeout=timeout, **request_args, ) response = Response(result) @@ -50,6 +54,26 @@ def handle( response.body, dict ): error_model_class = request.errors[response.status] + if isinstance(error_model_class, TypeAdapter): + # TypeAdapter for anyOf/oneOf union type errors: parse into the correct variant + try: + parsed_body = error_model_class.validate_python( + response.body + ) + except Exception: + parsed_body = response.body + message = response.body.get("message") + if not isinstance(message, str): + message = ( + f"{response.status} error in request to: {request.url}" + ) + error = ApiError( + message=message, + status=response.status, + response=response, + ) + error.body = parsed_body + return None, error error = error_model_class(**response.body) if "message" not in response.body: error.message = ( @@ -73,14 +97,24 @@ def handle( def stream( self, request: Request ) -> Generator[Tuple[Optional[Response], Optional[Exception]], None, None]: + """ + Stream the request to the specified URL and yield response chunks. + Useful for handling large responses or server-sent events. + + :param request: The request to stream. + :return: A generator yielding response chunks and any errors that occurred. + """ try: request_args = self._get_request_data(request) + # Get timeout from config if available, otherwise use default + timeout = self._get_timeout_from_config(request) + result = requests.request( request.method, request.url, headers=request.headers, - timeout=self._timeout_in_seconds, + timeout=timeout, stream=True, **request_args, ) @@ -133,3 +167,15 @@ def _get_request_data(self, request: Request) -> dict: return {"files": files, "data": form_data} return {"data": data} + + def _get_timeout_from_config(self, request: Request) -> float: + """ + Get the timeout for the request from config or use default. + + :param Request request: The request object. + :return: The timeout in seconds. + :rtype: float + """ + if request.config and "timeout" in request.config: + return request.config["timeout"] / 1000 + return self._timeout_in_seconds diff --git a/src/signplus/net/request_chain/handlers/retry_handler.py b/src/signplus/net/request_chain/handlers/retry_handler.py index 6807d69..8238e3d 100644 --- a/src/signplus/net/request_chain/handlers/retry_handler.py +++ b/src/signplus/net/request_chain/handlers/retry_handler.py @@ -12,10 +12,15 @@ class RetryHandler(BaseHandler): """ Handler for retrying requests. - Retries the request if the previous handler in the chain returned an error or a response with a status code of 500 or higher. + Supports configurable retry attempts, exponential backoff with jitter, and specific status codes or HTTP methods to retry. :ivar int _max_attempts: The maximum number of retry attempts. - :ivar int _delay_in_milliseconds: The delay between retry attempts in milliseconds. + :ivar int _delay_in_milliseconds: The initial delay between retry attempts in milliseconds. + :ivar int _max_delay_in_milliseconds: The maximum delay between retry attempts in milliseconds (caps exponential backoff). + :ivar float _backoff_factor: Multiplier for exponential backoff. + :ivar int _jitter_in_milliseconds: Maximum random jitter in milliseconds to add to retry delays. + :ivar set[int] | None _status_codes_to_retry: Specific HTTP status codes to retry (None triggers default: 5xx + 408, 429). + :ivar set[str] _http_methods_to_retry: HTTP methods that are allowed to be retried. """ def __init__(self): @@ -25,12 +30,22 @@ def __init__(self): super().__init__() self._max_attempts = 3 self._delay_in_milliseconds = 150 + self._max_delay_in_milliseconds = 5000 + self._backoff_factor = 2 + self._jitter_in_milliseconds = 50 + self._status_codes_to_retry = None + self._http_methods_to_retry = { + m.upper() + for m in ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"] + } def handle( self, request: Request ) -> Tuple[Optional[Response], Optional[RequestError]]: """ - Retry the request if the response has a status code greater or equal to 500 or equal to 408 (timeout). + Retry the request based on configured retry settings. + Implements exponential backoff with optional jitter between retry attempts. + Per-request retry config (via request.config['retry']) overrides SDK defaults. :param Request request: The request to retry. :return: The response and any error that occurred. @@ -40,11 +55,14 @@ def handle( if self._next_handler is None: raise RequestError("Handler chain is incomplete") + retry_config = (request.config or {}).get("retry") or {} + max_attempts = retry_config.get("attempts", self._max_attempts) + response, error = self._next_handler.handle(request) try_count = 0 - while try_count < self._max_attempts and self._should_retry(error): - self._delay(try_count) + while try_count < max_attempts and self._should_retry(error, request): + self._delay(try_count, request) response, error = self._next_handler.handle(request) try_count += 1 @@ -54,7 +72,9 @@ def stream( self, request: Request ) -> Generator[Tuple[Optional[Response], Optional[RequestError]], None, None]: """ - Retry the request if the response has a status code greater or equal to 500 or equal to 408 (timeout). + Retry the request based on configured retry settings. + Implements exponential backoff with optional jitter between retry attempts. + Per-request retry config (via request.config['retry']) overrides SDK defaults. :param Request request: The request to retry. :return: The response and any error that occurred. @@ -65,15 +85,17 @@ def stream( raise RequestError("Handler chain is incomplete") try: + retry_config = (request.config or {}).get("retry") or {} + max_attempts = retry_config.get("attempts", self._max_attempts) try_count = 0 stream = self._next_handler.stream(request) while True: response, error = next(stream) - if try_count < self._max_attempts and self._should_retry(error): - self._delay(try_count) + if try_count < max_attempts and self._should_retry(error, request): + self._delay(try_count, request) try_count += 1 stream = self._next_handler.stream(request) # Retry the request - elif try_count >= self._max_attempts: + elif try_count >= max_attempts: yield response, error break else: @@ -82,20 +104,69 @@ def stream( except StopIteration: pass - def _delay(self, try_count: int) -> None: - jitter = random.uniform(0.5, 1.5) - delay = self._delay_in_milliseconds * (2**try_count) * jitter / 1000 - sleep(delay) + def _delay(self, try_count: int, request: Request) -> None: + """ + Calculate and apply delay before next retry attempt using exponential backoff. + Delay is capped at maximum delay and optional jitter is added. + Per-request retry config overrides SDK defaults. - def _should_retry(self, error: Optional[ApiError]) -> bool: + :param int try_count: Current retry attempt number (0-indexed). + :param Request request: The request being retried, used to read per-request retry config. """ - Determine whether the request should be retried. + retry_config = (request.config or {}).get("retry") or {} + base_delay = retry_config.get("delay_ms", self._delay_in_milliseconds) + max_delay = retry_config.get("max_delay_ms", self._max_delay_in_milliseconds) + backoff_factor = retry_config.get("backoff_factor", self._backoff_factor) + jitter = retry_config.get("jitter_ms", self._jitter_in_milliseconds) + + # Calculate exponential backoff: initialDelay * (backoffFactor ^ try_count) + delay = base_delay * (backoff_factor**try_count) + + # Cap at max delay + delay = min(delay, max_delay) + + # Add jitter: random value between 0 and jitter_ms + if jitter > 0: + delay += random.uniform(0, jitter) + + # Convert to seconds and sleep + sleep(delay / 1000) + + def _should_retry(self, error: Optional[ApiError], request: Request) -> bool: + """ + Determine whether the request should be retried based on status code and HTTP method. + By default, retries all 5xx server errors and specific 4xx client errors (408 Timeout, 429 Rate Limit). + Per-request retry config overrides SDK defaults for status codes and HTTP methods. - :param Optional[Response] response: The response from the previous handler. :param Optional[ApiError] error: The error from the previous handler. + :param Request request: The request being retried. :return: True if the request should be retried, False otherwise. :rtype: bool """ if not error: return False - return error.status == 408 or error.status >= 500 + + retry_config = (request.config or {}).get("retry") or {} + + # Check if status code is retryable + request_status_codes = retry_config.get("status_codes_to_retry") + if request_status_codes is not None: + should_retry_status = error.status in request_status_codes + elif self._status_codes_to_retry is not None: + should_retry_status = error.status in self._status_codes_to_retry + else: + # Default: retry 5xx, 408 (Timeout), 429 (Rate Limit) + should_retry_status = ( + error.status >= 500 or error.status == 408 or error.status == 429 + ) + + # Check if HTTP method is retryable + request_http_methods = retry_config.get("http_methods_to_retry") + if request_http_methods is not None: + should_retry_method = request.method.upper() in { + m.upper() for m in request_http_methods + } + else: + should_retry_method = request.method.upper() in self._http_methods_to_retry + + return should_retry_status and should_retry_method diff --git a/src/signplus/net/sdk_config.py b/src/signplus/net/sdk_config.py new file mode 100644 index 0000000..0e1ce6b --- /dev/null +++ b/src/signplus/net/sdk_config.py @@ -0,0 +1,63 @@ +from typing import TypedDict, Optional + +from ..net.environment import Environment + + +class RetryConfig(TypedDict, total=False): + """ + Configuration for retry behavior. + + :ivar int attempts: Maximum number of retry attempts. + :ivar int delay_ms: Delay in milliseconds between retries. + :ivar int max_delay_ms: Maximum delay in milliseconds between retries (caps exponential backoff). + :ivar float backoff_factor: Multiplier for exponential backoff (e.g., 2.0 for doubling delay each retry). + :ivar int jitter_ms: Maximum random jitter in milliseconds to add to retry delays. + :ivar list[int] status_codes_to_retry: Specific HTTP status codes to retry (overrides default 5xx + 408, 429). + :ivar list[str] http_methods_to_retry: HTTP methods to retry (e.g., ['GET', 'POST']). + """ + + attempts: int + delay_ms: int + max_delay_ms: int + backoff_factor: float + jitter_ms: int + status_codes_to_retry: list[int] + http_methods_to_retry: list[str] + + +class ValidationConfig(TypedDict, total=False): + """ + Configuration for response validation. + + :ivar bool response_validation: Whether to validate responses against schemas. + """ + + response_validation: bool + + +class SdkConfig(TypedDict, total=False): + """ + Configuration dictionary for SDK, service, method, and request-level overrides. + + Hierarchy (highest to lowest priority): + - Request config (passed directly to method call) + - Method config (set via set__config()) + - Service config (set via set_config()) + - SDK config (set at initialization) + + :ivar str base_url: Base URL for API requests. Can be a string URL or Environment enum. + :ivar Environment environment: Environment enum value for base URL. + :ivar int timeout: Request timeout in milliseconds. + :ivar str token: Bearer token for authentication. + :ivar str access_token: Access token for authentication (alias for token). + :ivar RetryConfig retry: Retry configuration. + :ivar ValidationConfig validation: Validation configuration. + """ + + base_url: str + environment: Environment + timeout: int + token: str + access_token: str + retry: RetryConfig + validation: ValidationConfig diff --git a/src/signplus/net/transport/api_error.py b/src/signplus/net/transport/api_error.py index cb4cdd5..c9ee413 100644 --- a/src/signplus/net/transport/api_error.py +++ b/src/signplus/net/transport/api_error.py @@ -1,9 +1,8 @@ -from ...models.utils.base_model import BaseModel from .response import Response from typing import Optional -class ApiError(BaseModel, Exception): +class ApiError(Exception): """ Class representing an API Error. @@ -26,3 +25,12 @@ def __init__( self.message = message self.status = status self.response = response + super().__init__(message) + + def __str__(self) -> str: + parts = [] + if self.status is not None: + parts.append(f"status={self.status}") + if self.message: + parts.append(self.message) + return ": ".join(parts) diff --git a/src/signplus/net/transport/request.py b/src/signplus/net/transport/request.py index 81fa33b..ce86fee 100644 --- a/src/signplus/net/transport/request.py +++ b/src/signplus/net/transport/request.py @@ -1,6 +1,9 @@ -from typing import Any, Set +from typing import Any, Set, TYPE_CHECKING from .utils import extract_original_data +if TYPE_CHECKING: + from ..sdk_config import SdkConfig + class Request: """ @@ -27,6 +30,7 @@ class Request: :ivar Any body: Request body. :ivar Set[str] scopes: List of scopes to include in the request. :ivar dict errors: Dictionary of HTTP status codes to error models. + :ivar SdkConfig config: Configuration dictionary for the request. """ def __init__(self): @@ -36,6 +40,7 @@ def __init__(self): self.body = None self.scopes = None self.errors = None + self.config: "SdkConfig" = None def set_url(self, url: str) -> "Request": """ @@ -105,6 +110,17 @@ def set_errors(self, errors: dict) -> "Request": self.errors = errors return self + def set_config(self, config: "SdkConfig") -> "Request": + """ + Set the configuration for the request. + + :param SdkConfig config: Configuration dictionary for the request. + :return: The updated Request object. + :rtype: Request + """ + self.config = config + return self + def __str__(self) -> str: """ Return a string representation of the Request object. diff --git a/src/signplus/net/transport/response.py b/src/signplus/net/transport/response.py index 5824044..f1bacb8 100644 --- a/src/signplus/net/transport/response.py +++ b/src/signplus/net/transport/response.py @@ -1,7 +1,7 @@ import json import re from typing import Generator, Optional, Union -from requests import Response as RequestsResponse +from requests import Response from urllib.parse import parse_qs @@ -13,19 +13,21 @@ class Response: :ivar dict headers: The headers of the HTTP response. :ivar str body: The body of the HTTP response. :var str chunk: The chunk of the HTTP response. + :property Response raw: The original requests.Response object. """ def __init__( self, - response: RequestsResponse, + response: Response, chunk: Optional[str] = None, raw_chunk: Optional[bytes] = None, ) -> None: """ Initializes a Response object. - :param RequestsResponse response: The requests.Response object. + :param Response response: The Response object. """ + self._raw_response = response self.status = response.status_code self.headers = response.headers @@ -37,12 +39,12 @@ def __init__( @staticmethod def from_chunk( - response: RequestsResponse, raw_chunk: bytes + response: Response, raw_chunk: bytes ) -> Generator["Response", None, None]: """ Create a Response object from a chunk of data. - :param RequestsResponse response: The requests.Response object. + :param Response response: The Response object. :param bytes chunk: The chunk of data. :return: A Response object. :rtype: Response @@ -67,6 +69,16 @@ def __str__(self) -> str: f"Response(status={self.status}, headers={self.headers}, body={self.body})" ) + @property + def raw(self) -> Response: + """ + Get the underlying requests.Response object. + + :return: The original requests.Response object. + :rtype: Response + """ + return self._raw_response + def _parse_response_body( self, content_type: str, body: str, raw_body: bytes ) -> Union[str, dict, bytes]: @@ -79,7 +91,9 @@ def _parse_response_body( If the content type is 'application/x-www-form-urlencoded', it parses the body as a query string. For all other content types, it returns the raw binary content. - :param RequestsResponse response: The HTTP response received from a request. + :param str content_type: The content type of the response. + :param str body: The text body of the response. + :param bytes raw_body: The raw binary body of the response. :return: The parsed response body. :rtype: str or dict or bytes """ @@ -92,7 +106,11 @@ def _parse_response_body( # Note: this assumes that the content of data is a valid JSON string return json.loads(json_body) - if "text/" in content_type or content_type == "application/xml": + if ( + "text/" in content_type + or content_type == "application/xml" + or content_type == "application/javascript" + ): return body if content_type == "application/x-www-form-urlencoded": diff --git a/src/signplus/net/transport/serializer.py b/src/signplus/net/transport/serializer.py index d258dd4..4692a83 100644 --- a/src/signplus/net/transport/serializer.py +++ b/src/signplus/net/transport/serializer.py @@ -1,4 +1,4 @@ -from typing import Any, List +from typing import Any, List, Optional, TYPE_CHECKING from urllib.parse import quote from .request import Request @@ -7,6 +7,9 @@ from ...net.headers.base_header import BaseHeader from ...net.transport.api_error import ApiError +if TYPE_CHECKING: + from ...net.sdk_config import SdkConfig + class Serializer: """ @@ -18,14 +21,21 @@ class Serializer: :ivar dict[str, str] path: A dictionary containing path parameters for the request. :ivar list[str] query: A list containing query parameters for the request. :ivar dict[int, ApiError] errors: A dictionary of HTTP status codes to error models. + :ivar SdkConfig config: Configuration dictionary for the request. """ - def __init__(self, url: str, default_headers: List[BaseHeader] = []): + def __init__( + self, + url: str, + default_headers: List[BaseHeader] = [], + config: Optional["SdkConfig"] = None, + ): """ - Initializes a Serializer instance with the base URL. + Initializes a Serializer instance with the base URL and configuration. :param str url: The base URL to be serialized. - :param list[BaseHeader] default_headers: A list of default headers to be added to the request. Defaults to an empty list. + :param list[BaseHeader] default_headers: A list of default headers to be added to the request (with config overrides already applied). Defaults to an empty list. + :param SdkConfig config: Configuration dictionary for timeout and other non-auth settings. """ self.url: str = url self.headers: dict[str, str] = {} @@ -33,7 +43,13 @@ def __init__(self, url: str, default_headers: List[BaseHeader] = []): self.path: dict[str, str] = {} self.query: list[str] = [] self.errors: dict[int, ApiError] = {} + self.config: Optional["SdkConfig"] = config + + self.headers["User-Agent"] = ( + "postman-codegen/1.5.0 signplus-python/3.1.0 (python)" + ) + # Apply default headers for header in default_headers: for key, value in header.get_headers().items(): self.add_header(key, value) @@ -219,6 +235,7 @@ def serialize(self) -> Request: .set_url(final_url) .set_headers(self.headers) .set_errors(self.errors) + .set_config(self.config) ) def _define_url(self) -> str: diff --git a/src/signplus/net/transport/utils.py b/src/signplus/net/transport/utils.py index ca12a77..7ccb062 100644 --- a/src/signplus/net/transport/utils.py +++ b/src/signplus/net/transport/utils.py @@ -7,6 +7,8 @@ def extract_original_data(data: Any) -> Any: """ Extracts the original data from internal models and enums. + Supports both Pydantic models (model_dump_original) and legacy models (_map). + :param Any data: The data to be extracted. :return: The extracted data. :rtype: Any @@ -17,7 +19,15 @@ def extract_original_data(data: Any) -> Any: data_type = type(data) if issubclass(data_type, BaseModel): - return data._map() + # Pydantic models: use model_dump_original() + if hasattr(data, "model_dump_original"): + return data.model_dump_original() + # Legacy models: use _map() + elif hasattr(data, "_map"): + return data._map() + # Fallback: try to convert to dict + else: + return dict(data) if issubclass(data_type, Enum): return data.value diff --git a/src/signplus/sdk.py b/src/signplus/sdk.py index c5ab162..0713b88 100644 --- a/src/signplus/sdk.py +++ b/src/signplus/sdk.py @@ -4,6 +4,12 @@ class Signplus: + """ + Main SDK client class for Signplus. + Provides centralized configuration and access to all service endpoints. + Supports authentication, environment management, and global timeout settings. + """ + def __init__( self, access_token: str = None, @@ -14,9 +20,10 @@ def __init__( Initializes Signplus the SDK class. """ - self._base_url = ( + _resolved_url = ( base_url.value if isinstance(base_url, Environment) else base_url ) + self._base_url = _resolved_url.rstrip("/") if _resolved_url else _resolved_url self.signplus = SignplusService(base_url=self._base_url) self.set_access_token(access_token) self.set_timeout(timeout) @@ -28,9 +35,10 @@ def set_base_url(self, base_url: Union[Environment, str]): :param Union[Environment, str] base_url: The base URL to be set. :return: The SDK instance. """ - self._base_url = ( + _resolved_url = ( base_url.value if isinstance(base_url, Environment) else base_url ) + self._base_url = _resolved_url.rstrip("/") if _resolved_url else _resolved_url self.signplus.set_base_url(self._base_url) diff --git a/src/signplus/services/async_/signplus.py b/src/signplus/services/async_/signplus.py index c0ebbfe..fc9a240 100644 --- a/src/signplus/services/async_/signplus.py +++ b/src/signplus/services/async_/signplus.py @@ -1,6 +1,7 @@ -from typing import Awaitable, List +from typing import Awaitable, Optional, List from .utils.to_async import to_async from ..signplus import SignplusService +from ...net.sdk_config import SdkConfig from ...models.utils.sentinel import SENTINEL from ...models import ( Envelope, @@ -48,231 +49,467 @@ class SignplusServiceAsync(SignplusService): """ def create_envelope( - self, request_body: CreateEnvelopeRequest + self, + request_body: CreateEnvelopeRequest, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Envelope]: - return to_async(super().create_envelope)(request_body) + return to_async(super().create_envelope)( + request_body, request_config=request_config + ) def create_envelope_from_template( - self, request_body: CreateEnvelopeFromTemplateRequest, template_id: str + self, + request_body: CreateEnvelopeFromTemplateRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Envelope]: return to_async(super().create_envelope_from_template)( - request_body, template_id + request_body, template_id, request_config=request_config ) def list_envelopes( - self, request_body: ListEnvelopesRequest = None + self, + request_body: ListEnvelopesRequest = None, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[ListEnvelopesResponse]: - return to_async(super().list_envelopes)(request_body) + return to_async(super().list_envelopes)( + request_body, request_config=request_config + ) - def get_envelope(self, envelope_id: str) -> Awaitable[Envelope]: - return to_async(super().get_envelope)(envelope_id) + def get_envelope( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Awaitable[Envelope]: + return to_async(super().get_envelope)( + envelope_id, request_config=request_config + ) - def delete_envelope(self, envelope_id: str) -> Awaitable[None]: - return to_async(super().delete_envelope)(envelope_id) + def delete_envelope( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Awaitable[None]: + return to_async(super().delete_envelope)( + envelope_id, request_config=request_config + ) def download_envelope_signed_documents( - self, envelope_id: str, certificate_of_completion: bool = SENTINEL + self, + envelope_id: str, + certificate_of_completion: bool = SENTINEL, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[any]: return to_async(super().download_envelope_signed_documents)( - envelope_id, certificate_of_completion + envelope_id, certificate_of_completion, request_config=request_config ) - def download_envelope_certificate(self, envelope_id: str) -> Awaitable[any]: - return to_async(super().download_envelope_certificate)(envelope_id) + def download_envelope_certificate( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Awaitable[any]: + return to_async(super().download_envelope_certificate)( + envelope_id, request_config=request_config + ) def get_envelope_document( - self, envelope_id: str, document_id: str + self, + envelope_id: str, + document_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Document]: - return to_async(super().get_envelope_document)(envelope_id, document_id) + return to_async(super().get_envelope_document)( + envelope_id, document_id, request_config=request_config + ) def get_envelope_documents( - self, envelope_id: str + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None ) -> Awaitable[ListEnvelopeDocumentsResponse]: - return to_async(super().get_envelope_documents)(envelope_id) + return to_async(super().get_envelope_documents)( + envelope_id, request_config=request_config + ) def add_envelope_document( - self, request_body: AddEnvelopeDocumentRequest, envelope_id: str + self, + request_body: AddEnvelopeDocumentRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Document]: - return to_async(super().add_envelope_document)(request_body, envelope_id) + return to_async(super().add_envelope_document)( + request_body, envelope_id, request_config=request_config + ) def set_envelope_dynamic_fields( - self, request_body: SetEnvelopeDynamicFieldsRequest, envelope_id: str + self, + request_body: SetEnvelopeDynamicFieldsRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Envelope]: - return to_async(super().set_envelope_dynamic_fields)(request_body, envelope_id) + return to_async(super().set_envelope_dynamic_fields)( + request_body, envelope_id, request_config=request_config + ) def add_envelope_signing_steps( - self, request_body: AddEnvelopeSigningStepsRequest, envelope_id: str + self, + request_body: AddEnvelopeSigningStepsRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Envelope]: - return to_async(super().add_envelope_signing_steps)(request_body, envelope_id) + return to_async(super().add_envelope_signing_steps)( + request_body, envelope_id, request_config=request_config + ) def set_envelope_attachments_settings( - self, request_body: SetEnvelopeAttachmentsSettingsRequest, envelope_id: str + self, + request_body: SetEnvelopeAttachmentsSettingsRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[EnvelopeAttachments]: return to_async(super().set_envelope_attachments_settings)( - request_body, envelope_id + request_body, envelope_id, request_config=request_config ) def set_envelope_attachments_placeholders( - self, request_body: SetEnvelopeAttachmentsPlaceholdersRequest, envelope_id: str + self, + request_body: SetEnvelopeAttachmentsPlaceholdersRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[EnvelopeAttachments]: return to_async(super().set_envelope_attachments_placeholders)( - request_body, envelope_id + request_body, envelope_id, request_config=request_config ) - def get_attachment_file(self, envelope_id: str, file_id: str) -> Awaitable[bytes]: - return to_async(super().get_attachment_file)(envelope_id, file_id) + def get_attachment_file( + self, + envelope_id: str, + file_id: str, + *, + request_config: Optional[SdkConfig] = None, + ) -> Awaitable[bytes]: + return to_async(super().get_attachment_file)( + envelope_id, file_id, request_config=request_config + ) - def send_envelope(self, envelope_id: str) -> Awaitable[Envelope]: - return to_async(super().send_envelope)(envelope_id) + def send_envelope( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Awaitable[Envelope]: + return to_async(super().send_envelope)( + envelope_id, request_config=request_config + ) - def duplicate_envelope(self, envelope_id: str) -> Awaitable[Envelope]: - return to_async(super().duplicate_envelope)(envelope_id) + def duplicate_envelope( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Awaitable[Envelope]: + return to_async(super().duplicate_envelope)( + envelope_id, request_config=request_config + ) - def void_envelope(self, envelope_id: str) -> Awaitable[Envelope]: - return to_async(super().void_envelope)(envelope_id) + def void_envelope( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Awaitable[Envelope]: + return to_async(super().void_envelope)( + envelope_id, request_config=request_config + ) def rename_envelope( - self, request_body: RenameEnvelopeRequest, envelope_id: str + self, + request_body: RenameEnvelopeRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Envelope]: - return to_async(super().rename_envelope)(request_body, envelope_id) + return to_async(super().rename_envelope)( + request_body, envelope_id, request_config=request_config + ) def set_envelope_comment( - self, request_body: SetEnvelopeCommentRequest, envelope_id: str + self, + request_body: SetEnvelopeCommentRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Envelope]: - return to_async(super().set_envelope_comment)(request_body, envelope_id) + return to_async(super().set_envelope_comment)( + request_body, envelope_id, request_config=request_config + ) def set_envelope_notification( - self, request_body: EnvelopeNotification, envelope_id: str + self, + request_body: EnvelopeNotification, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Envelope]: - return to_async(super().set_envelope_notification)(request_body, envelope_id) + return to_async(super().set_envelope_notification)( + request_body, envelope_id, request_config=request_config + ) def set_envelope_expiration_date( - self, request_body: SetEnvelopeExpirationRequest, envelope_id: str + self, + request_body: SetEnvelopeExpirationRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Envelope]: - return to_async(super().set_envelope_expiration_date)(request_body, envelope_id) + return to_async(super().set_envelope_expiration_date)( + request_body, envelope_id, request_config=request_config + ) def set_envelope_legality_level( - self, request_body: SetEnvelopeLegalityLevelRequest, envelope_id: str + self, + request_body: SetEnvelopeLegalityLevelRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Envelope]: - return to_async(super().set_envelope_legality_level)(request_body, envelope_id) + return to_async(super().set_envelope_legality_level)( + request_body, envelope_id, request_config=request_config + ) - def get_envelope_annotations(self, envelope_id: str) -> Awaitable[List[Annotation]]: - return to_async(super().get_envelope_annotations)(envelope_id) + def get_envelope_annotations( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Awaitable[List[Annotation]]: + return to_async(super().get_envelope_annotations)( + envelope_id, request_config=request_config + ) def get_envelope_document_annotations( - self, envelope_id: str, document_id: str + self, + envelope_id: str, + document_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[ListEnvelopeDocumentAnnotationsResponse]: return to_async(super().get_envelope_document_annotations)( - envelope_id, document_id + envelope_id, document_id, request_config=request_config ) def add_envelope_annotation( - self, request_body: AddAnnotationRequest, envelope_id: str + self, + request_body: AddAnnotationRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Annotation]: - return to_async(super().add_envelope_annotation)(request_body, envelope_id) + return to_async(super().add_envelope_annotation)( + request_body, envelope_id, request_config=request_config + ) def delete_envelope_annotation( - self, envelope_id: str, annotation_id: str + self, + envelope_id: str, + annotation_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[None]: - return to_async(super().delete_envelope_annotation)(envelope_id, annotation_id) + return to_async(super().delete_envelope_annotation)( + envelope_id, annotation_id, request_config=request_config + ) def create_template( - self, request_body: CreateTemplateRequest + self, + request_body: CreateTemplateRequest, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Template]: - return to_async(super().create_template)(request_body) + return to_async(super().create_template)( + request_body, request_config=request_config + ) def list_templates( - self, request_body: ListTemplatesRequest = None + self, + request_body: ListTemplatesRequest = None, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[ListTemplatesResponse]: - return to_async(super().list_templates)(request_body) + return to_async(super().list_templates)( + request_body, request_config=request_config + ) - def get_template(self, template_id: str) -> Awaitable[Template]: - return to_async(super().get_template)(template_id) + def get_template( + self, template_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Awaitable[Template]: + return to_async(super().get_template)( + template_id, request_config=request_config + ) - def delete_template(self, template_id: str) -> Awaitable[None]: - return to_async(super().delete_template)(template_id) + def delete_template( + self, template_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Awaitable[None]: + return to_async(super().delete_template)( + template_id, request_config=request_config + ) - def duplicate_template(self, template_id: str) -> Awaitable[Template]: - return to_async(super().duplicate_template)(template_id) + def duplicate_template( + self, template_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Awaitable[Template]: + return to_async(super().duplicate_template)( + template_id, request_config=request_config + ) def add_template_document( - self, request_body: AddTemplateDocumentRequest, template_id: str + self, + request_body: AddTemplateDocumentRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Document]: - return to_async(super().add_template_document)(request_body, template_id) + return to_async(super().add_template_document)( + request_body, template_id, request_config=request_config + ) def get_template_document( - self, template_id: str, document_id: str + self, + template_id: str, + document_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Document]: - return to_async(super().get_template_document)(template_id, document_id) + return to_async(super().get_template_document)( + template_id, document_id, request_config=request_config + ) def get_template_documents( - self, template_id: str + self, template_id: str, *, request_config: Optional[SdkConfig] = None ) -> Awaitable[ListTemplateDocumentsResponse]: - return to_async(super().get_template_documents)(template_id) + return to_async(super().get_template_documents)( + template_id, request_config=request_config + ) def add_template_signing_steps( - self, request_body: AddTemplateSigningStepsRequest, template_id: str + self, + request_body: AddTemplateSigningStepsRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Template]: - return to_async(super().add_template_signing_steps)(request_body, template_id) + return to_async(super().add_template_signing_steps)( + request_body, template_id, request_config=request_config + ) def rename_template( - self, request_body: RenameTemplateRequest, template_id: str + self, + request_body: RenameTemplateRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Template]: - return to_async(super().rename_template)(request_body, template_id) + return to_async(super().rename_template)( + request_body, template_id, request_config=request_config + ) def set_template_comment( - self, request_body: SetTemplateCommentRequest, template_id: str + self, + request_body: SetTemplateCommentRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Template]: - return to_async(super().set_template_comment)(request_body, template_id) + return to_async(super().set_template_comment)( + request_body, template_id, request_config=request_config + ) def set_template_notification( - self, request_body: EnvelopeNotification, template_id: str + self, + request_body: EnvelopeNotification, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Template]: - return to_async(super().set_template_notification)(request_body, template_id) + return to_async(super().set_template_notification)( + request_body, template_id, request_config=request_config + ) def get_template_annotations( - self, template_id: str + self, template_id: str, *, request_config: Optional[SdkConfig] = None ) -> Awaitable[ListTemplateAnnotationsResponse]: - return to_async(super().get_template_annotations)(template_id) + return to_async(super().get_template_annotations)( + template_id, request_config=request_config + ) def get_document_template_annotations( - self, template_id: str, document_id: str + self, + template_id: str, + document_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[ListTemplateDocumentAnnotationsResponse]: return to_async(super().get_document_template_annotations)( - template_id, document_id + template_id, document_id, request_config=request_config ) def add_template_annotation( - self, request_body: AddAnnotationRequest, template_id: str + self, + request_body: AddAnnotationRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[Annotation]: - return to_async(super().add_template_annotation)(request_body, template_id) + return to_async(super().add_template_annotation)( + request_body, template_id, request_config=request_config + ) def delete_template_annotation( - self, template_id: str, annotation_id: str + self, + template_id: str, + annotation_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[None]: - return to_async(super().delete_template_annotation)(template_id, annotation_id) + return to_async(super().delete_template_annotation)( + template_id, annotation_id, request_config=request_config + ) def set_template_attachments_settings( - self, request_body: SetEnvelopeAttachmentsSettingsRequest, template_id: str + self, + request_body: SetEnvelopeAttachmentsSettingsRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[EnvelopeAttachments]: return to_async(super().set_template_attachments_settings)( - request_body, template_id + request_body, template_id, request_config=request_config ) def set_template_attachments_placeholders( - self, request_body: SetEnvelopeAttachmentsPlaceholdersRequest, template_id: str + self, + request_body: SetEnvelopeAttachmentsPlaceholdersRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[EnvelopeAttachments]: return to_async(super().set_template_attachments_placeholders)( - request_body, template_id + request_body, template_id, request_config=request_config ) - def create_webhook(self, request_body: CreateWebhookRequest) -> Awaitable[Webhook]: - return to_async(super().create_webhook)(request_body) + def create_webhook( + self, + request_body: CreateWebhookRequest, + *, + request_config: Optional[SdkConfig] = None, + ) -> Awaitable[Webhook]: + return to_async(super().create_webhook)( + request_body, request_config=request_config + ) def list_webhooks( - self, request_body: ListWebhooksRequest = None + self, + request_body: ListWebhooksRequest = None, + *, + request_config: Optional[SdkConfig] = None, ) -> Awaitable[ListWebhooksResponse]: - return to_async(super().list_webhooks)(request_body) + return to_async(super().list_webhooks)( + request_body, request_config=request_config + ) - def delete_webhook(self, webhook_id: str) -> Awaitable[None]: - return to_async(super().delete_webhook)(webhook_id) + def delete_webhook( + self, webhook_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Awaitable[None]: + return to_async(super().delete_webhook)( + webhook_id, request_config=request_config + ) diff --git a/src/signplus/services/signplus.py b/src/signplus/services/signplus.py index c1cc15d..250d060 100644 --- a/src/signplus/services/signplus.py +++ b/src/signplus/services/signplus.py @@ -1,7 +1,8 @@ -from typing import List +from typing import Any, Optional, List from .utils.validator import Validator from .utils.base_service import BaseService from ..net.transport.serializer import Serializer +from ..net.sdk_config import SdkConfig from ..net.environment.environment import Environment from ..models.utils.sentinel import SENTINEL from ..models.utils.cast_models import cast_models @@ -46,9 +47,551 @@ class SignplusService(BaseService): + """ + Service class for SignplusService operations. + Provides methods to interact with SignplusService-related API endpoints. + Inherits common functionality from BaseService including authentication and request handling. + """ + + def __init__(self, *args, **kwargs): + """Initialize the service and method-level configurations.""" + super().__init__(*args, **kwargs) + self._create_envelope_config: SdkConfig = {} + self._create_envelope_from_template_config: SdkConfig = {} + self._list_envelopes_config: SdkConfig = {} + self._get_envelope_config: SdkConfig = {} + self._delete_envelope_config: SdkConfig = {} + self._download_envelope_signed_documents_config: SdkConfig = {} + self._download_envelope_certificate_config: SdkConfig = {} + self._get_envelope_document_config: SdkConfig = {} + self._get_envelope_documents_config: SdkConfig = {} + self._add_envelope_document_config: SdkConfig = {} + self._set_envelope_dynamic_fields_config: SdkConfig = {} + self._add_envelope_signing_steps_config: SdkConfig = {} + self._set_envelope_attachments_settings_config: SdkConfig = {} + self._set_envelope_attachments_placeholders_config: SdkConfig = {} + self._get_attachment_file_config: SdkConfig = {} + self._send_envelope_config: SdkConfig = {} + self._duplicate_envelope_config: SdkConfig = {} + self._void_envelope_config: SdkConfig = {} + self._rename_envelope_config: SdkConfig = {} + self._set_envelope_comment_config: SdkConfig = {} + self._set_envelope_notification_config: SdkConfig = {} + self._set_envelope_expiration_date_config: SdkConfig = {} + self._set_envelope_legality_level_config: SdkConfig = {} + self._get_envelope_annotations_config: SdkConfig = {} + self._get_envelope_document_annotations_config: SdkConfig = {} + self._add_envelope_annotation_config: SdkConfig = {} + self._delete_envelope_annotation_config: SdkConfig = {} + self._create_template_config: SdkConfig = {} + self._list_templates_config: SdkConfig = {} + self._get_template_config: SdkConfig = {} + self._delete_template_config: SdkConfig = {} + self._duplicate_template_config: SdkConfig = {} + self._add_template_document_config: SdkConfig = {} + self._get_template_document_config: SdkConfig = {} + self._get_template_documents_config: SdkConfig = {} + self._add_template_signing_steps_config: SdkConfig = {} + self._rename_template_config: SdkConfig = {} + self._set_template_comment_config: SdkConfig = {} + self._set_template_notification_config: SdkConfig = {} + self._get_template_annotations_config: SdkConfig = {} + self._get_document_template_annotations_config: SdkConfig = {} + self._add_template_annotation_config: SdkConfig = {} + self._delete_template_annotation_config: SdkConfig = {} + self._set_template_attachments_settings_config: SdkConfig = {} + self._set_template_attachments_placeholders_config: SdkConfig = {} + self._create_webhook_config: SdkConfig = {} + self._list_webhooks_config: SdkConfig = {} + self._delete_webhook_config: SdkConfig = {} + + def set_create_envelope_config(self, config: SdkConfig): + """ + Sets method-level configuration for create_envelope. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._create_envelope_config = config + return self + + def set_create_envelope_from_template_config(self, config: SdkConfig): + """ + Sets method-level configuration for create_envelope_from_template. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._create_envelope_from_template_config = config + return self + + def set_list_envelopes_config(self, config: SdkConfig): + """ + Sets method-level configuration for list_envelopes. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._list_envelopes_config = config + return self + + def set_get_envelope_config(self, config: SdkConfig): + """ + Sets method-level configuration for get_envelope. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._get_envelope_config = config + return self + + def set_delete_envelope_config(self, config: SdkConfig): + """ + Sets method-level configuration for delete_envelope. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._delete_envelope_config = config + return self + + def set_download_envelope_signed_documents_config(self, config: SdkConfig): + """ + Sets method-level configuration for download_envelope_signed_documents. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._download_envelope_signed_documents_config = config + return self + + def set_download_envelope_certificate_config(self, config: SdkConfig): + """ + Sets method-level configuration for download_envelope_certificate. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._download_envelope_certificate_config = config + return self + + def set_get_envelope_document_config(self, config: SdkConfig): + """ + Sets method-level configuration for get_envelope_document. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._get_envelope_document_config = config + return self + + def set_get_envelope_documents_config(self, config: SdkConfig): + """ + Sets method-level configuration for get_envelope_documents. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._get_envelope_documents_config = config + return self + + def set_add_envelope_document_config(self, config: SdkConfig): + """ + Sets method-level configuration for add_envelope_document. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._add_envelope_document_config = config + return self + + def set_set_envelope_dynamic_fields_config(self, config: SdkConfig): + """ + Sets method-level configuration for set_envelope_dynamic_fields. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._set_envelope_dynamic_fields_config = config + return self + + def set_add_envelope_signing_steps_config(self, config: SdkConfig): + """ + Sets method-level configuration for add_envelope_signing_steps. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._add_envelope_signing_steps_config = config + return self + + def set_set_envelope_attachments_settings_config(self, config: SdkConfig): + """ + Sets method-level configuration for set_envelope_attachments_settings. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._set_envelope_attachments_settings_config = config + return self + + def set_set_envelope_attachments_placeholders_config(self, config: SdkConfig): + """ + Sets method-level configuration for set_envelope_attachments_placeholders. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._set_envelope_attachments_placeholders_config = config + return self + + def set_get_attachment_file_config(self, config: SdkConfig): + """ + Sets method-level configuration for get_attachment_file. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._get_attachment_file_config = config + return self + + def set_send_envelope_config(self, config: SdkConfig): + """ + Sets method-level configuration for send_envelope. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._send_envelope_config = config + return self + + def set_duplicate_envelope_config(self, config: SdkConfig): + """ + Sets method-level configuration for duplicate_envelope. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._duplicate_envelope_config = config + return self + + def set_void_envelope_config(self, config: SdkConfig): + """ + Sets method-level configuration for void_envelope. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._void_envelope_config = config + return self + + def set_rename_envelope_config(self, config: SdkConfig): + """ + Sets method-level configuration for rename_envelope. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._rename_envelope_config = config + return self + + def set_set_envelope_comment_config(self, config: SdkConfig): + """ + Sets method-level configuration for set_envelope_comment. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._set_envelope_comment_config = config + return self + + def set_set_envelope_notification_config(self, config: SdkConfig): + """ + Sets method-level configuration for set_envelope_notification. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._set_envelope_notification_config = config + return self + + def set_set_envelope_expiration_date_config(self, config: SdkConfig): + """ + Sets method-level configuration for set_envelope_expiration_date. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._set_envelope_expiration_date_config = config + return self + + def set_set_envelope_legality_level_config(self, config: SdkConfig): + """ + Sets method-level configuration for set_envelope_legality_level. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._set_envelope_legality_level_config = config + return self + + def set_get_envelope_annotations_config(self, config: SdkConfig): + """ + Sets method-level configuration for get_envelope_annotations. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._get_envelope_annotations_config = config + return self + + def set_get_envelope_document_annotations_config(self, config: SdkConfig): + """ + Sets method-level configuration for get_envelope_document_annotations. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._get_envelope_document_annotations_config = config + return self + + def set_add_envelope_annotation_config(self, config: SdkConfig): + """ + Sets method-level configuration for add_envelope_annotation. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._add_envelope_annotation_config = config + return self + + def set_delete_envelope_annotation_config(self, config: SdkConfig): + """ + Sets method-level configuration for delete_envelope_annotation. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._delete_envelope_annotation_config = config + return self + + def set_create_template_config(self, config: SdkConfig): + """ + Sets method-level configuration for create_template. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._create_template_config = config + return self + + def set_list_templates_config(self, config: SdkConfig): + """ + Sets method-level configuration for list_templates. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._list_templates_config = config + return self + + def set_get_template_config(self, config: SdkConfig): + """ + Sets method-level configuration for get_template. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._get_template_config = config + return self + + def set_delete_template_config(self, config: SdkConfig): + """ + Sets method-level configuration for delete_template. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._delete_template_config = config + return self + + def set_duplicate_template_config(self, config: SdkConfig): + """ + Sets method-level configuration for duplicate_template. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._duplicate_template_config = config + return self + + def set_add_template_document_config(self, config: SdkConfig): + """ + Sets method-level configuration for add_template_document. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._add_template_document_config = config + return self + + def set_get_template_document_config(self, config: SdkConfig): + """ + Sets method-level configuration for get_template_document. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._get_template_document_config = config + return self + + def set_get_template_documents_config(self, config: SdkConfig): + """ + Sets method-level configuration for get_template_documents. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._get_template_documents_config = config + return self + + def set_add_template_signing_steps_config(self, config: SdkConfig): + """ + Sets method-level configuration for add_template_signing_steps. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._add_template_signing_steps_config = config + return self + + def set_rename_template_config(self, config: SdkConfig): + """ + Sets method-level configuration for rename_template. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._rename_template_config = config + return self + + def set_set_template_comment_config(self, config: SdkConfig): + """ + Sets method-level configuration for set_template_comment. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._set_template_comment_config = config + return self + + def set_set_template_notification_config(self, config: SdkConfig): + """ + Sets method-level configuration for set_template_notification. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._set_template_notification_config = config + return self + + def set_get_template_annotations_config(self, config: SdkConfig): + """ + Sets method-level configuration for get_template_annotations. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._get_template_annotations_config = config + return self + + def set_get_document_template_annotations_config(self, config: SdkConfig): + """ + Sets method-level configuration for get_document_template_annotations. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._get_document_template_annotations_config = config + return self + + def set_add_template_annotation_config(self, config: SdkConfig): + """ + Sets method-level configuration for add_template_annotation. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._add_template_annotation_config = config + return self + + def set_delete_template_annotation_config(self, config: SdkConfig): + """ + Sets method-level configuration for delete_template_annotation. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._delete_template_annotation_config = config + return self + + def set_set_template_attachments_settings_config(self, config: SdkConfig): + """ + Sets method-level configuration for set_template_attachments_settings. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._set_template_attachments_settings_config = config + return self + + def set_set_template_attachments_placeholders_config(self, config: SdkConfig): + """ + Sets method-level configuration for set_template_attachments_placeholders. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._set_template_attachments_placeholders_config = config + return self + + def set_create_webhook_config(self, config: SdkConfig): + """ + Sets method-level configuration for create_webhook. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._create_webhook_config = config + return self + + def set_list_webhooks_config(self, config: SdkConfig): + """ + Sets method-level configuration for list_webhooks. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._list_webhooks_config = config + return self + + def set_delete_webhook_config(self, config: SdkConfig): + """ + Sets method-level configuration for delete_webhook. + + :param SdkConfig config: Configuration dictionary to override service-level defaults. + :return: The service instance for method chaining. + """ + self._delete_webhook_config = config + return self @cast_models - def create_envelope(self, request_body: CreateEnvelopeRequest) -> Envelope: + def create_envelope( + self, + request_body: CreateEnvelopeRequest, + *, + request_config: Optional[SdkConfig] = None, + ) -> Envelope: """Create new envelope :param request_body: The request body. @@ -62,10 +605,15 @@ def create_envelope(self, request_body: CreateEnvelopeRequest) -> Envelope: Validator(CreateEnvelopeRequest).validate(request_body) + resolved_config = self._get_resolved_config( + self._create_envelope_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope", + [self.get_access_token(resolved_config)], + resolved_config, ) .serialize() .set_method("POST") @@ -73,11 +621,15 @@ def create_envelope(self, request_body: CreateEnvelopeRequest) -> Envelope: ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models def create_envelope_from_template( - self, request_body: CreateEnvelopeFromTemplateRequest, template_id: str + self, + request_body: CreateEnvelopeFromTemplateRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Envelope: """Create new envelope from template @@ -95,10 +647,15 @@ def create_envelope_from_template( Validator(CreateEnvelopeFromTemplateRequest).validate(request_body) Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._create_envelope_from_template_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/from_template/{{template_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/from_template/{{template_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -107,11 +664,14 @@ def create_envelope_from_template( ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models def list_envelopes( - self, request_body: ListEnvelopesRequest = None + self, + request_body: ListEnvelopesRequest = None, + *, + request_config: Optional[SdkConfig] = None, ) -> ListEnvelopesResponse: """List envelopes @@ -126,10 +686,15 @@ def list_envelopes( Validator(ListEnvelopesRequest).is_optional().validate(request_body) + resolved_config = self._get_resolved_config( + self._list_envelopes_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelopes", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelopes", + [self.get_access_token(resolved_config)], + resolved_config, ) .serialize() .set_method("POST") @@ -137,10 +702,12 @@ def list_envelopes( ) response, _, _ = self.send_request(serialized_request) - return ListEnvelopesResponse._unmap(response) + return ListEnvelopesResponse.model_validate(response) @cast_models - def get_envelope(self, envelope_id: str) -> Envelope: + def get_envelope( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Envelope: """Get envelope :param envelope_id: envelope_id @@ -154,10 +721,15 @@ def get_envelope(self, envelope_id: str) -> Envelope: Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._get_envelope_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -165,10 +737,12 @@ def get_envelope(self, envelope_id: str) -> Envelope: ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models - def delete_envelope(self, envelope_id: str) -> None: + def delete_envelope( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> None: """Delete envelope :param envelope_id: envelope_id @@ -180,10 +754,15 @@ def delete_envelope(self, envelope_id: str) -> None: Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._delete_envelope_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -194,7 +773,11 @@ def delete_envelope(self, envelope_id: str) -> None: @cast_models def download_envelope_signed_documents( - self, envelope_id: str, certificate_of_completion: bool = SENTINEL + self, + envelope_id: str, + certificate_of_completion: bool = SENTINEL, + *, + request_config: Optional[SdkConfig] = None, ) -> any: """Download signed documents for an envelope @@ -212,10 +795,15 @@ def download_envelope_signed_documents( Validator(str).validate(envelope_id) Validator(bool).is_optional().validate(certificate_of_completion) + resolved_config = self._get_resolved_config( + self._download_envelope_signed_documents_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/signed_documents", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/signed_documents", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .add_query("certificate_of_completion", certificate_of_completion) @@ -227,7 +815,9 @@ def download_envelope_signed_documents( return response @cast_models - def download_envelope_certificate(self, envelope_id: str) -> any: + def download_envelope_certificate( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> any: """Download certificate of completion for an envelope :param envelope_id: ID of the envelope @@ -241,10 +831,15 @@ def download_envelope_certificate(self, envelope_id: str) -> any: Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._download_envelope_certificate_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/certificate", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/certificate", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -255,7 +850,13 @@ def download_envelope_certificate(self, envelope_id: str) -> any: return response @cast_models - def get_envelope_document(self, envelope_id: str, document_id: str) -> Document: + def get_envelope_document( + self, + envelope_id: str, + document_id: str, + *, + request_config: Optional[SdkConfig] = None, + ) -> Document: """Get envelope document :param envelope_id: envelope_id @@ -272,10 +873,15 @@ def get_envelope_document(self, envelope_id: str, document_id: str) -> Document: Validator(str).validate(envelope_id) Validator(str).validate(document_id) + resolved_config = self._get_resolved_config( + self._get_envelope_document_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/document/{{document_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/document/{{document_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .add_path("document_id", document_id) @@ -284,10 +890,12 @@ def get_envelope_document(self, envelope_id: str, document_id: str) -> Document: ) response, _, _ = self.send_request(serialized_request) - return Document._unmap(response) + return Document.model_validate(response) @cast_models - def get_envelope_documents(self, envelope_id: str) -> ListEnvelopeDocumentsResponse: + def get_envelope_documents( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> ListEnvelopeDocumentsResponse: """Get envelope documents :param envelope_id: envelope_id @@ -301,10 +909,15 @@ def get_envelope_documents(self, envelope_id: str) -> ListEnvelopeDocumentsRespo Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._get_envelope_documents_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/documents", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/documents", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -312,11 +925,15 @@ def get_envelope_documents(self, envelope_id: str) -> ListEnvelopeDocumentsRespo ) response, _, _ = self.send_request(serialized_request) - return ListEnvelopeDocumentsResponse._unmap(response) + return ListEnvelopeDocumentsResponse.model_validate(response) @cast_models def add_envelope_document( - self, request_body: AddEnvelopeDocumentRequest, envelope_id: str + self, + request_body: AddEnvelopeDocumentRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Document: """Add envelope document @@ -334,10 +951,15 @@ def add_envelope_document( Validator(AddEnvelopeDocumentRequest).validate(request_body) Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._add_envelope_document_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/document", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/document", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -346,11 +968,15 @@ def add_envelope_document( ) response, _, _ = self.send_request(serialized_request) - return Document._unmap(response) + return Document.model_validate(response) @cast_models def set_envelope_dynamic_fields( - self, request_body: SetEnvelopeDynamicFieldsRequest, envelope_id: str + self, + request_body: SetEnvelopeDynamicFieldsRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Envelope: """Set envelope dynamic fields @@ -368,10 +994,15 @@ def set_envelope_dynamic_fields( Validator(SetEnvelopeDynamicFieldsRequest).validate(request_body) Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._set_envelope_dynamic_fields_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/dynamic_fields", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/dynamic_fields", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -380,11 +1011,15 @@ def set_envelope_dynamic_fields( ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models def add_envelope_signing_steps( - self, request_body: AddEnvelopeSigningStepsRequest, envelope_id: str + self, + request_body: AddEnvelopeSigningStepsRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Envelope: """Add envelope signing steps @@ -402,10 +1037,15 @@ def add_envelope_signing_steps( Validator(AddEnvelopeSigningStepsRequest).validate(request_body) Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._add_envelope_signing_steps_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/signing_steps", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/signing_steps", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -414,11 +1054,15 @@ def add_envelope_signing_steps( ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models def set_envelope_attachments_settings( - self, request_body: SetEnvelopeAttachmentsSettingsRequest, envelope_id: str + self, + request_body: SetEnvelopeAttachmentsSettingsRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> EnvelopeAttachments: """Set envelope attachment settings @@ -436,10 +1080,15 @@ def set_envelope_attachments_settings( Validator(SetEnvelopeAttachmentsSettingsRequest).validate(request_body) Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._set_envelope_attachments_settings_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/attachments/settings", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/attachments/settings", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -448,11 +1097,15 @@ def set_envelope_attachments_settings( ) response, _, _ = self.send_request(serialized_request) - return EnvelopeAttachments._unmap(response) + return EnvelopeAttachments.model_validate(response) @cast_models def set_envelope_attachments_placeholders( - self, request_body: SetEnvelopeAttachmentsPlaceholdersRequest, envelope_id: str + self, + request_body: SetEnvelopeAttachmentsPlaceholdersRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> EnvelopeAttachments: """Placeholders to be set, completely replacing the existing ones. @@ -470,10 +1123,15 @@ def set_envelope_attachments_placeholders( Validator(SetEnvelopeAttachmentsPlaceholdersRequest).validate(request_body) Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._set_envelope_attachments_placeholders_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/attachments/placeholders", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/attachments/placeholders", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -482,10 +1140,16 @@ def set_envelope_attachments_placeholders( ) response, _, _ = self.send_request(serialized_request) - return EnvelopeAttachments._unmap(response) + return EnvelopeAttachments.model_validate(response) @cast_models - def get_attachment_file(self, envelope_id: str, file_id: str) -> bytes: + def get_attachment_file( + self, + envelope_id: str, + file_id: str, + *, + request_config: Optional[SdkConfig] = None, + ) -> bytes: """Get envelope attachment file :param envelope_id: envelope_id @@ -502,10 +1166,15 @@ def get_attachment_file(self, envelope_id: str, file_id: str) -> bytes: Validator(str).validate(envelope_id) Validator(str).validate(file_id) + resolved_config = self._get_resolved_config( + self._get_attachment_file_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/attachments/{{file_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/attachments/{{file_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .add_path("file_id", file_id) @@ -517,7 +1186,9 @@ def get_attachment_file(self, envelope_id: str, file_id: str) -> bytes: return response @cast_models - def send_envelope(self, envelope_id: str) -> Envelope: + def send_envelope( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Envelope: """Send envelope for signature :param envelope_id: envelope_id @@ -531,10 +1202,15 @@ def send_envelope(self, envelope_id: str) -> Envelope: Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._send_envelope_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/send", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/send", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -542,10 +1218,12 @@ def send_envelope(self, envelope_id: str) -> Envelope: ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models - def duplicate_envelope(self, envelope_id: str) -> Envelope: + def duplicate_envelope( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Envelope: """Duplicate envelope :param envelope_id: envelope_id @@ -559,10 +1237,15 @@ def duplicate_envelope(self, envelope_id: str) -> Envelope: Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._duplicate_envelope_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/duplicate", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/duplicate", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -570,10 +1253,12 @@ def duplicate_envelope(self, envelope_id: str) -> Envelope: ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models - def void_envelope(self, envelope_id: str) -> Envelope: + def void_envelope( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Envelope: """Void envelope :param envelope_id: envelope_id @@ -587,10 +1272,15 @@ def void_envelope(self, envelope_id: str) -> Envelope: Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._void_envelope_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/void", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/void", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -598,11 +1288,15 @@ def void_envelope(self, envelope_id: str) -> Envelope: ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models def rename_envelope( - self, request_body: RenameEnvelopeRequest, envelope_id: str + self, + request_body: RenameEnvelopeRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Envelope: """Rename envelope @@ -620,10 +1314,15 @@ def rename_envelope( Validator(RenameEnvelopeRequest).validate(request_body) Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._rename_envelope_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/rename", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/rename", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -632,11 +1331,15 @@ def rename_envelope( ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models def set_envelope_comment( - self, request_body: SetEnvelopeCommentRequest, envelope_id: str + self, + request_body: SetEnvelopeCommentRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Envelope: """Set envelope comment @@ -654,10 +1357,15 @@ def set_envelope_comment( Validator(SetEnvelopeCommentRequest).validate(request_body) Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._set_envelope_comment_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/set_comment", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/set_comment", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -666,11 +1374,15 @@ def set_envelope_comment( ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models def set_envelope_notification( - self, request_body: EnvelopeNotification, envelope_id: str + self, + request_body: EnvelopeNotification, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Envelope: """Set envelope notification @@ -688,10 +1400,15 @@ def set_envelope_notification( Validator(EnvelopeNotification).validate(request_body) Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._set_envelope_notification_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/set_notification", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/set_notification", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -700,11 +1417,15 @@ def set_envelope_notification( ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models def set_envelope_expiration_date( - self, request_body: SetEnvelopeExpirationRequest, envelope_id: str + self, + request_body: SetEnvelopeExpirationRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Envelope: """Set envelope expiration date @@ -722,10 +1443,15 @@ def set_envelope_expiration_date( Validator(SetEnvelopeExpirationRequest).validate(request_body) Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._set_envelope_expiration_date_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/set_expiration_date", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/set_expiration_date", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -734,11 +1460,15 @@ def set_envelope_expiration_date( ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models def set_envelope_legality_level( - self, request_body: SetEnvelopeLegalityLevelRequest, envelope_id: str + self, + request_body: SetEnvelopeLegalityLevelRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Envelope: """Set envelope legality level @@ -756,10 +1486,15 @@ def set_envelope_legality_level( Validator(SetEnvelopeLegalityLevelRequest).validate(request_body) Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._set_envelope_legality_level_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/set_legality_level", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/set_legality_level", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -768,10 +1503,12 @@ def set_envelope_legality_level( ) response, _, _ = self.send_request(serialized_request) - return Envelope._unmap(response) + return Envelope.model_validate(response) @cast_models - def get_envelope_annotations(self, envelope_id: str) -> List[Annotation]: + def get_envelope_annotations( + self, envelope_id: str, *, request_config: Optional[SdkConfig] = None + ) -> List[Annotation]: """Get envelope annotations :param envelope_id: ID of the envelope @@ -785,10 +1522,15 @@ def get_envelope_annotations(self, envelope_id: str) -> List[Annotation]: Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._get_envelope_annotations_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/annotations", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/annotations", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -796,11 +1538,15 @@ def get_envelope_annotations(self, envelope_id: str) -> List[Annotation]: ) response, _, _ = self.send_request(serialized_request) - return [Annotation._unmap(item) for item in response] + return [Annotation.model_validate(item) for item in response] @cast_models def get_envelope_document_annotations( - self, envelope_id: str, document_id: str + self, + envelope_id: str, + document_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> ListEnvelopeDocumentAnnotationsResponse: """Get envelope document annotations @@ -818,10 +1564,15 @@ def get_envelope_document_annotations( Validator(str).validate(envelope_id) Validator(str).validate(document_id) + resolved_config = self._get_resolved_config( + self._get_envelope_document_annotations_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/annotations/{{document_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/annotations/{{document_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .add_path("document_id", document_id) @@ -830,11 +1581,15 @@ def get_envelope_document_annotations( ) response, _, _ = self.send_request(serialized_request) - return ListEnvelopeDocumentAnnotationsResponse._unmap(response) + return ListEnvelopeDocumentAnnotationsResponse.model_validate(response) @cast_models def add_envelope_annotation( - self, request_body: AddAnnotationRequest, envelope_id: str + self, + request_body: AddAnnotationRequest, + envelope_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Annotation: """Add envelope annotation @@ -852,10 +1607,15 @@ def add_envelope_annotation( Validator(AddAnnotationRequest).validate(request_body) Validator(str).validate(envelope_id) + resolved_config = self._get_resolved_config( + self._add_envelope_annotation_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/annotation", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/annotation", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .serialize() @@ -864,10 +1624,16 @@ def add_envelope_annotation( ) response, _, _ = self.send_request(serialized_request) - return Annotation._unmap(response) + return Annotation.model_validate(response) @cast_models - def delete_envelope_annotation(self, envelope_id: str, annotation_id: str) -> None: + def delete_envelope_annotation( + self, + envelope_id: str, + annotation_id: str, + *, + request_config: Optional[SdkConfig] = None, + ) -> None: """Delete envelope annotation :param envelope_id: ID of the envelope @@ -882,10 +1648,15 @@ def delete_envelope_annotation(self, envelope_id: str, annotation_id: str) -> No Validator(str).validate(envelope_id) Validator(str).validate(annotation_id) + resolved_config = self._get_resolved_config( + self._delete_envelope_annotation_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/annotation/{{annotation_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/envelope/{{envelope_id}}/annotation/{{annotation_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("envelope_id", envelope_id) .add_path("annotation_id", annotation_id) @@ -896,7 +1667,12 @@ def delete_envelope_annotation(self, envelope_id: str, annotation_id: str) -> No self.send_request(serialized_request) @cast_models - def create_template(self, request_body: CreateTemplateRequest) -> Template: + def create_template( + self, + request_body: CreateTemplateRequest, + *, + request_config: Optional[SdkConfig] = None, + ) -> Template: """Create new template :param request_body: The request body. @@ -910,10 +1686,15 @@ def create_template(self, request_body: CreateTemplateRequest) -> Template: Validator(CreateTemplateRequest).validate(request_body) + resolved_config = self._get_resolved_config( + self._create_template_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template", + [self.get_access_token(resolved_config)], + resolved_config, ) .serialize() .set_method("POST") @@ -921,11 +1702,14 @@ def create_template(self, request_body: CreateTemplateRequest) -> Template: ) response, _, _ = self.send_request(serialized_request) - return Template._unmap(response) + return Template.model_validate(response) @cast_models def list_templates( - self, request_body: ListTemplatesRequest = None + self, + request_body: ListTemplatesRequest = None, + *, + request_config: Optional[SdkConfig] = None, ) -> ListTemplatesResponse: """List templates @@ -940,10 +1724,15 @@ def list_templates( Validator(ListTemplatesRequest).is_optional().validate(request_body) + resolved_config = self._get_resolved_config( + self._list_templates_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/templates", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/templates", + [self.get_access_token(resolved_config)], + resolved_config, ) .serialize() .set_method("POST") @@ -951,10 +1740,12 @@ def list_templates( ) response, _, _ = self.send_request(serialized_request) - return ListTemplatesResponse._unmap(response) + return ListTemplatesResponse.model_validate(response) @cast_models - def get_template(self, template_id: str) -> Template: + def get_template( + self, template_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Template: """Get template :param template_id: template_id @@ -968,10 +1759,15 @@ def get_template(self, template_id: str) -> Template: Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._get_template_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -979,10 +1775,12 @@ def get_template(self, template_id: str) -> Template: ) response, _, _ = self.send_request(serialized_request) - return Template._unmap(response) + return Template.model_validate(response) @cast_models - def delete_template(self, template_id: str) -> None: + def delete_template( + self, template_id: str, *, request_config: Optional[SdkConfig] = None + ) -> None: """Delete template :param template_id: template_id @@ -994,10 +1792,15 @@ def delete_template(self, template_id: str) -> None: Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._delete_template_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -1007,7 +1810,9 @@ def delete_template(self, template_id: str) -> None: self.send_request(serialized_request) @cast_models - def duplicate_template(self, template_id: str) -> Template: + def duplicate_template( + self, template_id: str, *, request_config: Optional[SdkConfig] = None + ) -> Template: """Duplicate template :param template_id: template_id @@ -1021,10 +1826,15 @@ def duplicate_template(self, template_id: str) -> Template: Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._duplicate_template_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/duplicate", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/duplicate", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -1032,11 +1842,15 @@ def duplicate_template(self, template_id: str) -> Template: ) response, _, _ = self.send_request(serialized_request) - return Template._unmap(response) + return Template.model_validate(response) @cast_models def add_template_document( - self, request_body: AddTemplateDocumentRequest, template_id: str + self, + request_body: AddTemplateDocumentRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Document: """Add template document @@ -1054,10 +1868,15 @@ def add_template_document( Validator(AddTemplateDocumentRequest).validate(request_body) Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._add_template_document_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/document", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/document", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -1066,10 +1885,16 @@ def add_template_document( ) response, _, _ = self.send_request(serialized_request) - return Document._unmap(response) + return Document.model_validate(response) @cast_models - def get_template_document(self, template_id: str, document_id: str) -> Document: + def get_template_document( + self, + template_id: str, + document_id: str, + *, + request_config: Optional[SdkConfig] = None, + ) -> Document: """Get template document :param template_id: template_id @@ -1086,10 +1911,15 @@ def get_template_document(self, template_id: str, document_id: str) -> Document: Validator(str).validate(template_id) Validator(str).validate(document_id) + resolved_config = self._get_resolved_config( + self._get_template_document_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/document/{{document_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/document/{{document_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .add_path("document_id", document_id) @@ -1098,10 +1928,12 @@ def get_template_document(self, template_id: str, document_id: str) -> Document: ) response, _, _ = self.send_request(serialized_request) - return Document._unmap(response) + return Document.model_validate(response) @cast_models - def get_template_documents(self, template_id: str) -> ListTemplateDocumentsResponse: + def get_template_documents( + self, template_id: str, *, request_config: Optional[SdkConfig] = None + ) -> ListTemplateDocumentsResponse: """Get template documents :param template_id: template_id @@ -1115,10 +1947,15 @@ def get_template_documents(self, template_id: str) -> ListTemplateDocumentsRespo Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._get_template_documents_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/documents", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/documents", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -1126,11 +1963,15 @@ def get_template_documents(self, template_id: str) -> ListTemplateDocumentsRespo ) response, _, _ = self.send_request(serialized_request) - return ListTemplateDocumentsResponse._unmap(response) + return ListTemplateDocumentsResponse.model_validate(response) @cast_models def add_template_signing_steps( - self, request_body: AddTemplateSigningStepsRequest, template_id: str + self, + request_body: AddTemplateSigningStepsRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Template: """Add template signing steps @@ -1148,10 +1989,15 @@ def add_template_signing_steps( Validator(AddTemplateSigningStepsRequest).validate(request_body) Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._add_template_signing_steps_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/signing_steps", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/signing_steps", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -1160,11 +2006,15 @@ def add_template_signing_steps( ) response, _, _ = self.send_request(serialized_request) - return Template._unmap(response) + return Template.model_validate(response) @cast_models def rename_template( - self, request_body: RenameTemplateRequest, template_id: str + self, + request_body: RenameTemplateRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Template: """Rename template @@ -1182,10 +2032,15 @@ def rename_template( Validator(RenameTemplateRequest).validate(request_body) Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._rename_template_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/rename", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/rename", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -1194,11 +2049,15 @@ def rename_template( ) response, _, _ = self.send_request(serialized_request) - return Template._unmap(response) + return Template.model_validate(response) @cast_models def set_template_comment( - self, request_body: SetTemplateCommentRequest, template_id: str + self, + request_body: SetTemplateCommentRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Template: """Set template comment @@ -1216,10 +2075,15 @@ def set_template_comment( Validator(SetTemplateCommentRequest).validate(request_body) Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._set_template_comment_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/set_comment", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/set_comment", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -1228,11 +2092,15 @@ def set_template_comment( ) response, _, _ = self.send_request(serialized_request) - return Template._unmap(response) + return Template.model_validate(response) @cast_models def set_template_notification( - self, request_body: EnvelopeNotification, template_id: str + self, + request_body: EnvelopeNotification, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Template: """Set template notification @@ -1250,10 +2118,15 @@ def set_template_notification( Validator(EnvelopeNotification).validate(request_body) Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._set_template_notification_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/set_notification", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/set_notification", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -1262,11 +2135,11 @@ def set_template_notification( ) response, _, _ = self.send_request(serialized_request) - return Template._unmap(response) + return Template.model_validate(response) @cast_models def get_template_annotations( - self, template_id: str + self, template_id: str, *, request_config: Optional[SdkConfig] = None ) -> ListTemplateAnnotationsResponse: """Get template annotations @@ -1281,10 +2154,15 @@ def get_template_annotations( Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._get_template_annotations_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/annotations", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/annotations", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -1292,11 +2170,15 @@ def get_template_annotations( ) response, _, _ = self.send_request(serialized_request) - return ListTemplateAnnotationsResponse._unmap(response) + return ListTemplateAnnotationsResponse.model_validate(response) @cast_models def get_document_template_annotations( - self, template_id: str, document_id: str + self, + template_id: str, + document_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> ListTemplateDocumentAnnotationsResponse: """Get document template annotations @@ -1314,10 +2196,15 @@ def get_document_template_annotations( Validator(str).validate(template_id) Validator(str).validate(document_id) + resolved_config = self._get_resolved_config( + self._get_document_template_annotations_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/annotations/{{document_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/annotations/{{document_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .add_path("document_id", document_id) @@ -1326,11 +2213,15 @@ def get_document_template_annotations( ) response, _, _ = self.send_request(serialized_request) - return ListTemplateDocumentAnnotationsResponse._unmap(response) + return ListTemplateDocumentAnnotationsResponse.model_validate(response) @cast_models def add_template_annotation( - self, request_body: AddAnnotationRequest, template_id: str + self, + request_body: AddAnnotationRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> Annotation: """Add template annotation @@ -1348,10 +2239,15 @@ def add_template_annotation( Validator(AddAnnotationRequest).validate(request_body) Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._add_template_annotation_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/annotation", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/annotation", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -1360,10 +2256,16 @@ def add_template_annotation( ) response, _, _ = self.send_request(serialized_request) - return Annotation._unmap(response) + return Annotation.model_validate(response) @cast_models - def delete_template_annotation(self, template_id: str, annotation_id: str) -> None: + def delete_template_annotation( + self, + template_id: str, + annotation_id: str, + *, + request_config: Optional[SdkConfig] = None, + ) -> None: """Delete template annotation :param template_id: ID of the template @@ -1378,10 +2280,15 @@ def delete_template_annotation(self, template_id: str, annotation_id: str) -> No Validator(str).validate(template_id) Validator(str).validate(annotation_id) + resolved_config = self._get_resolved_config( + self._delete_template_annotation_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/annotation/{{annotation_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/annotation/{{annotation_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .add_path("annotation_id", annotation_id) @@ -1393,7 +2300,11 @@ def delete_template_annotation(self, template_id: str, annotation_id: str) -> No @cast_models def set_template_attachments_settings( - self, request_body: SetEnvelopeAttachmentsSettingsRequest, template_id: str + self, + request_body: SetEnvelopeAttachmentsSettingsRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> EnvelopeAttachments: """Set template attachment settings @@ -1411,10 +2322,15 @@ def set_template_attachments_settings( Validator(SetEnvelopeAttachmentsSettingsRequest).validate(request_body) Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._set_template_attachments_settings_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/attachments/settings", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/attachments/settings", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -1423,11 +2339,15 @@ def set_template_attachments_settings( ) response, _, _ = self.send_request(serialized_request) - return EnvelopeAttachments._unmap(response) + return EnvelopeAttachments.model_validate(response) @cast_models def set_template_attachments_placeholders( - self, request_body: SetEnvelopeAttachmentsPlaceholdersRequest, template_id: str + self, + request_body: SetEnvelopeAttachmentsPlaceholdersRequest, + template_id: str, + *, + request_config: Optional[SdkConfig] = None, ) -> EnvelopeAttachments: """Placeholders to be set, completely replacing the existing ones. @@ -1445,10 +2365,15 @@ def set_template_attachments_placeholders( Validator(SetEnvelopeAttachmentsPlaceholdersRequest).validate(request_body) Validator(str).validate(template_id) + resolved_config = self._get_resolved_config( + self._set_template_attachments_placeholders_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/attachments/placeholders", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/template/{{template_id}}/attachments/placeholders", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("template_id", template_id) .serialize() @@ -1457,10 +2382,15 @@ def set_template_attachments_placeholders( ) response, _, _ = self.send_request(serialized_request) - return EnvelopeAttachments._unmap(response) + return EnvelopeAttachments.model_validate(response) @cast_models - def create_webhook(self, request_body: CreateWebhookRequest) -> Webhook: + def create_webhook( + self, + request_body: CreateWebhookRequest, + *, + request_config: Optional[SdkConfig] = None, + ) -> Webhook: """Create webhook :param request_body: The request body. @@ -1474,10 +2404,15 @@ def create_webhook(self, request_body: CreateWebhookRequest) -> Webhook: Validator(CreateWebhookRequest).validate(request_body) + resolved_config = self._get_resolved_config( + self._create_webhook_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/webhook", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/webhook", + [self.get_access_token(resolved_config)], + resolved_config, ) .serialize() .set_method("POST") @@ -1485,11 +2420,14 @@ def create_webhook(self, request_body: CreateWebhookRequest) -> Webhook: ) response, _, _ = self.send_request(serialized_request) - return Webhook._unmap(response) + return Webhook.model_validate(response) @cast_models def list_webhooks( - self, request_body: ListWebhooksRequest = None + self, + request_body: ListWebhooksRequest = None, + *, + request_config: Optional[SdkConfig] = None, ) -> ListWebhooksResponse: """List webhooks @@ -1504,10 +2442,15 @@ def list_webhooks( Validator(ListWebhooksRequest).is_optional().validate(request_body) + resolved_config = self._get_resolved_config( + self._list_webhooks_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/webhooks", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/webhooks", + [self.get_access_token(resolved_config)], + resolved_config, ) .serialize() .set_method("POST") @@ -1515,10 +2458,12 @@ def list_webhooks( ) response, _, _ = self.send_request(serialized_request) - return ListWebhooksResponse._unmap(response) + return ListWebhooksResponse.model_validate(response) @cast_models - def delete_webhook(self, webhook_id: str) -> None: + def delete_webhook( + self, webhook_id: str, *, request_config: Optional[SdkConfig] = None + ) -> None: """Delete webhook :param webhook_id: webhook_id @@ -1530,10 +2475,15 @@ def delete_webhook(self, webhook_id: str) -> None: Validator(str).validate(webhook_id) + resolved_config = self._get_resolved_config( + self._delete_webhook_config, request_config + ) + serialized_request = ( Serializer( - f"{self.base_url or Environment.DEFAULT.url}/webhook/{{webhook_id}}", - [self.get_access_token()], + f"{resolved_config.get('base_url') or self.base_url or Environment.DEFAULT.url}/webhook/{{webhook_id}}", + [self.get_access_token(resolved_config)], + resolved_config, ) .add_path("webhook_id", webhook_id) .serialize() diff --git a/src/signplus/services/utils/base_service.py b/src/signplus/services/utils/base_service.py index db2e2d5..4db3a29 100644 --- a/src/signplus/services/utils/base_service.py +++ b/src/signplus/services/utils/base_service.py @@ -1,4 +1,4 @@ -from typing import Any, Dict, Tuple, Generator +from typing import Any, Dict, Tuple, Generator, TYPE_CHECKING from enum import Enum from .default_headers import DefaultHeaders, DefaultHeadersKeys @@ -7,11 +7,13 @@ from ...net.transport.request import Request from ...net.request_chain.request_chain import RequestChain -from ...net.request_chain.handlers.hook_handler import HookHandler from ...net.request_chain.handlers.http_handler import HttpHandler from ...net.headers.access_token_auth import AccessTokenAuth from ...net.request_chain.handlers.retry_handler import RetryHandler +if TYPE_CHECKING: + from ...net.sdk_config import SdkConfig + class BaseService: """ @@ -27,9 +29,10 @@ def __init__(self, base_url: str) -> None: :param str base_url: The base URL for the service. Defaults to None. """ - self.base_url = base_url + self.base_url = base_url.rstrip("/") if base_url else base_url self._default_headers = DefaultHeaders() self._timeout = 60000 + self._service_config: "SdkConfig" = {} self._update_request_handler() @@ -43,13 +46,19 @@ def set_access_token(self, access_token: str): return self - def get_access_token(self) -> BaseHeader: + def get_access_token(self, resolved_config: "SdkConfig" = None) -> BaseHeader: """ - Get the access auth header. + Get the access auth header, with optional config overrides. + :param SdkConfig resolved_config: Optional resolved configuration for overrides. :return: The access auth header. :rtype: BaseHeader """ + if resolved_config and ( + "token" in resolved_config or "access_token" in resolved_config + ): + token = resolved_config.get("token") or resolved_config.get("access_token") + return AccessTokenAuth(token) return self._default_headers.get_header(DefaultHeadersKeys.ACCESS_AUTH) def set_timeout(self, timeout: int): @@ -70,10 +79,78 @@ def set_base_url(self, base_url: str): :param str base_url: The base URL to be set. """ - self.base_url = base_url + self.base_url = base_url.rstrip("/") if base_url else base_url + + return self + + def set_config(self, config: "SdkConfig"): + """ + Sets service-level configuration that applies to all methods in this service. + :param SdkConfig config: Configuration dictionary to override SDK-level defaults. + :return: The service instance for method chaining. + """ + self._service_config = config return self + @staticmethod + def _deep_merge(base: dict, override: dict) -> dict: + """ + Recursively merges two dictionaries. Nested dicts are merged key-by-key so + that a partial override (e.g. ``{"retry": {"attempts": 5}}``) only overwrites + the keys it specifies instead of replacing the entire nested dict. + + Every dict value from ``override`` is recursed into (creating a fresh dict), + so override sources are never shared by reference in the result. Unoverridden + nested values from ``base`` are shallow-copied at the top level via ``dict(base)``; + configs are consumed read-only downstream so this is intentional. + + :param dict base: The base dictionary. + :param dict override: Values to merge on top of base. + :return: A new merged dictionary. + :rtype: dict + """ + merged = dict(base) + for key, value in override.items(): + if isinstance(value, dict): + base_node = merged.get(key) + merged[key] = BaseService._deep_merge( + base_node if isinstance(base_node, dict) else {}, value + ) + else: + merged[key] = value + return merged + + def _get_resolved_config( + self, method_config: "SdkConfig" = None, request_config: "SdkConfig" = None + ) -> "SdkConfig": + """ + Resolves configuration overrides from the hierarchy: request_config > method_config > service_config. + Merges override configs into a single dictionary using deep merge so that partial + overrides for nested dicts (e.g. ``retry``) only replace the specified keys. + SDK defaults are used as fallbacks where these overrides are not provided. + + :param SdkConfig method_config: Method-level configuration override. + :param SdkConfig request_config: Request-level configuration override. + :return: Merged configuration with all overrides applied. + :rtype: SdkConfig + """ + resolved: "SdkConfig" = {} + + # Apply service config + if self._service_config: + resolved = BaseService._deep_merge(resolved, self._service_config) + + # Apply method config + if method_config: + resolved = BaseService._deep_merge(resolved, method_config) + + # Apply request config + if request_config: + resolved = BaseService._deep_merge(resolved, request_config) + + return resolved + def send_request(self, request: Request) -> Tuple[Dict, int, str]: """ Sends the given request. @@ -83,6 +160,7 @@ def send_request(self, request: Request) -> Tuple[Dict, int, str]: :rtype: Tuple[Dict, int, str] """ response = self._request_handler.send(request) + self._last_response = response return ( response.body, response.status, @@ -122,7 +200,6 @@ def _get_request_handler(self) -> RequestChain: """ return ( RequestChain() - .add_handler(HookHandler()) .add_handler(RetryHandler()) .add_handler(HttpHandler(self._timeout)) )