diff --git a/CHANGELOG.md b/CHANGELOG.md index 462f7d1d..06eb25e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Change Log +## 25.0.0 + +* Breaking: requests send `X-Appwrite-Response-Format: 2.5.0`; responses follow the 2.5 shapes +* Breaking: removed `account.list_logs`, `users.list_logs` and the `Log`/`LogList` models +* Breaking: removed `organization.create_key`, `get_key`, `list_keys`, `update_key` and `delete_key`, and `OrganizationKeyScopes`; use `organization.list_project_keys`, `get_project_key`, `update_project_key` and `delete_project_key` instead +* Breaking: removed `Client.set_dev_key`, the `DevKey` model and `Project.dev_keys` +* Breaking: removed `BillingPlanGroup.STARTER`; use `BillingPlanGroup.FREE` +* Breaking: `list_specifications` returns each specification's prices and overage rates on the row itself. Removed the list-level `pricing` field and the `DedicatedDatabaseSpecificationPricing` model +* Breaking: removed `Block` fields `reason`, `project_name`, `region`, `organization_name`, `organization_id` and `billing_plan` +* Breaking: OAuth2 `resource` params now take `List[str]` +* Breaking: `project.update_o_auth2_kakao` takes `enabled` before `prompt` +* Breaking: `BackupRestoration.options` is now a dict +* Breaking: some response fields became `Optional`, such as `BillingPlan.usage` and `DedicatedDatabase.engine` +* Added: `Topic` helper to build MQTT topics for push messages +* Added: `mongo`, `mysql` and `postgresql` `promote_restoration`, `restore_mode`, `target_name` and `auto_promote` on `create_restoration`, and `DedicatedDatabaseRestoration.restore_mode` +* Added: `proxy.create_smtp_rule`, the `ProxyRuleProtocol` enum and `ProxyRule.protocol` +* Added: `email_enabled` on `functions.update` and `Function`, and `ExecutionTrigger.EMAIL` +* Added: `Query` aggregates (`count`, `count_distinct`, `sum`, `avg`, `min`, `max` and more), `group_by`, `having`, `distinct`, joins, `relationship`, `covers`, `spatial_equals` and `page` +* Added: `Query.builder()` to chain queries; `build()` returns the query list +* Updated: missing response fields fall back to their documented defaults +* Fixed: map fields missing from a response default to `{}` instead of `[]` + ## 24.4.0 * Added: `domains` service to manage domains, DNS records, email presets, prices, transfer status and zones diff --git a/README.md b/README.md index e7644a3a..70f2aa7c 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # Appwrite Python SDK ![License](https://img.shields.io/github/license/appwrite/sdk-for-python.svg?style=flat-square) -![Version](https://img.shields.io/badge/api%20version-2.0.0-blue.svg?style=flat-square) +![Version](https://img.shields.io/badge/api%20version-2.5.0-blue.svg?style=flat-square) [![Build Status](https://img.shields.io/travis/com/appwrite/sdk-generator?style=flat-square)](https://travis-ci.com/appwrite/sdk-generator) [![Twitter Account](https://img.shields.io/twitter/follow/appwrite?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite) [![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord) -**This SDK targets Appwrite server version 1.9.x as shipped on Appwrite Cloud.** Self-hosted releases can lag behind Cloud — if you run an older self-hosted build, use a matching older SDK from [previous releases](https://github.com/appwrite/sdk-for-python/releases) when APIs differ. +**This SDK targets Appwrite server version 2.5.x as shipped on Appwrite Cloud.** Self-hosted releases can lag behind Cloud — if you run an older self-hosted build, use a matching older SDK from [previous releases](https://github.com/appwrite/sdk-for-python/releases) when APIs differ. Appwrite is an open-source backend as a service server that abstracts and simplifies complex and repetitive development tasks behind a very simple to use REST API. Appwrite aims to help you develop your apps faster and in a more secure way. Use the Python SDK to integrate your app with the Appwrite server to easily start interacting with all of Appwrite backend APIs and tools. For full API documentation and tutorials go to [https://appwrite.io/docs](https://appwrite.io/docs) diff --git a/appwrite/client.py b/appwrite/client.py index 94a60b40..49c7d754 100644 --- a/appwrite/client.py +++ b/appwrite/client.py @@ -9,6 +9,7 @@ from .input_file import InputFile from .exception import AppwriteException from .encoders.value_class_encoder import ValueClassEncoder +from .query import Query class Client: @@ -18,12 +19,12 @@ def __init__(self): self._endpoint = 'https://cloud.appwrite.io/v1' self._global_headers = { 'content-type': '', - 'user-agent': f'AppwritePythonSDK/24.4.0 ({platform.uname().system}; {platform.uname().version}; {platform.uname().machine})', + 'user-agent': f'AppwritePythonSDK/25.0.0 ({platform.uname().system}; {platform.uname().version}; {platform.uname().machine})', 'x-sdk-name': 'Python', 'x-sdk-platform': 'server', 'x-sdk-language': 'python', - 'x-sdk-version': '24.4.0', - 'X-Appwrite-Response-Format': '2.0.0', + 'x-sdk-version': '25.0.0', + 'X-Appwrite-Response-Format': '2.5.0', } self._config = {} @@ -101,13 +102,6 @@ def set_forwarded_user_agent(self, value): self._config['forwardeduseragent'] = value return self - def set_dev_key(self, value): - """Your secret dev API key""" - - self._global_headers['x-appwrite-dev-key'] = value - self._config['devkey'] = value - return self - def set_cookie(self, value): """The user cookie to authenticate with. Used by SDKs that forward an incoming Cookie header in server-side runtimes.""" @@ -143,6 +137,8 @@ def call(self, method, path='', headers=None, params=None, response_type='json') if params is None: params = {} + params = {key: Query._flatten(value) for key, value in params.items()} + data = {} files = {} stringify = False @@ -164,6 +160,15 @@ def call(self, method, path='', headers=None, params=None, response_type='json') files[key] = (data[key].filename, data[key].data) del data[key] data = self.flatten(data, stringify=stringify) + if not files and data: + # Without a file, requests would fall back to a URL-encoded body. + files = {key: (None, value) for key, value in data.items()} + data = {} + elif not files: + # With no parts at all, requests would send a bare body, so close an empty multipart one. + boundary = os.urandom(16).hex() + headers['content-type'] = f'multipart/form-data; boundary={boundary}' + data = f'--{boundary}--\r\n' response = None try: @@ -217,8 +222,12 @@ def chunked_upload( param_name='', on_progress=None, upload_id='', + response_type='json', method='post', ): + if params.get(param_name) is None: + return self.call(method, path, headers, params, response_type=response_type) + input_file = params[param_name] if input_file.source_type == 'path': @@ -228,13 +237,13 @@ def chunked_upload( size = len(input_file.data) input = input_file.data - if size < self._chunk_size: + if size <= self._chunk_size or response_type == 'text': if input_file.source_type == 'path': with open(input_file.path, 'rb') as input: input_file.data = input.read() params[param_name] = input_file - return self.call(method, path, headers, params) + return self.call(method, path, headers, params, response_type=response_type) offset = 0 counter = 0 @@ -281,6 +290,8 @@ def read_chunk(start, end): final_result = None def is_upload_complete(chunk_result): + if not isinstance(chunk_result, dict): + return False chunks_uploaded = chunk_result.get('chunksUploaded') if chunks_uploaded is None: return False @@ -304,11 +315,12 @@ def upload_chunk(chunk, current_upload_id): path, chunk_headers, chunk_params, + response_type=response_type, ) result = upload_chunk(chunks[0], upload_id_header) last_result = result - if "$id" in result: + if isinstance(result, dict) and "$id" in result: upload_id_header = result["$id"] completed_count = chunks[0]['index'] + 1 @@ -317,7 +329,7 @@ def upload_chunk(chunk, current_upload_id): if on_progress is not None: on_progress( { - "$id": result.get("$id"), + "$id": result.get("$id") if isinstance(result, dict) else None, "progress": uploaded_size / size * 100, "sizeUploaded": uploaded_size, "chunksTotal": total_chunks, @@ -354,13 +366,10 @@ def upload_remaining_chunk(chunk): def flatten(self, data, prefix='', stringify=False): output = {} - i = 0 + entries = data.items() if isinstance(data, dict) else enumerate(data) - for key in data: - value = data[key] if isinstance(data, dict) else key - finalKey = prefix + '[' + key + ']' if prefix else key - finalKey = prefix + '[' + str(i) + ']' if isinstance(data, list) else finalKey - i += 1 + for key, value in entries: + finalKey = f'{prefix}[{key}]' if prefix or isinstance(data, list) else key if isinstance(value, list) or isinstance(value, dict): output = {**output, **self.flatten(value, finalKey, stringify)} diff --git a/appwrite/encoders/value_class_encoder.py b/appwrite/encoders/value_class_encoder.py index 46727dad..f157b094 100644 --- a/appwrite/encoders/value_class_encoder.py +++ b/appwrite/encoders/value_class_encoder.py @@ -27,7 +27,6 @@ from ..enums.execution_method import ExecutionMethod from ..enums.message_priority import MessagePriority from ..enums.smtp_encryption import SmtpEncryption -from ..enums.organization_key_scopes import OrganizationKeyScopes from ..enums.region import Region from ..enums.project_auth_method_id import ProjectAuthMethodId from ..enums.project_o_auth2_auth0_prompt import ProjectOAuth2Auth0Prompt @@ -81,6 +80,7 @@ from ..enums.platform_type import PlatformType from ..enums.proxy_rule_deployment_resource_type import ProxyRuleDeploymentResourceType from ..enums.proxy_rule_status import ProxyRuleStatus +from ..enums.proxy_rule_protocol import ProxyRuleProtocol from ..enums.message_status import MessageStatus from ..enums.billing_plan_group import BillingPlanGroup from ..enums.domain_transfer_status_enum import DomainTransferStatusEnum @@ -173,9 +173,6 @@ def default(self, o): if isinstance(o, SmtpEncryption): return o.value - if isinstance(o, OrganizationKeyScopes): - return o.value - if isinstance(o, Region): return o.value @@ -335,6 +332,9 @@ def default(self, o): if isinstance(o, ProxyRuleStatus): return o.value + if isinstance(o, ProxyRuleProtocol): + return o.value + if isinstance(o, MessageStatus): return o.value diff --git a/appwrite/enums/billing_plan_group.py b/appwrite/enums/billing_plan_group.py index e161dd24..b2b23a29 100644 --- a/appwrite/enums/billing_plan_group.py +++ b/appwrite/enums/billing_plan_group.py @@ -2,7 +2,6 @@ class BillingPlanGroup(Enum): - STARTER = "starter" FREE = "free" START = "start" PRO = "pro" diff --git a/appwrite/enums/execution_trigger.py b/appwrite/enums/execution_trigger.py index 02b7c791..472fe719 100644 --- a/appwrite/enums/execution_trigger.py +++ b/appwrite/enums/execution_trigger.py @@ -5,3 +5,4 @@ class ExecutionTrigger(Enum): HTTP = "http" SCHEDULE = "schedule" EVENT = "event" + EMAIL = "email" diff --git a/appwrite/enums/organization_key_scopes.py b/appwrite/enums/organization_key_scopes.py deleted file mode 100644 index ffa6e6a6..00000000 --- a/appwrite/enums/organization_key_scopes.py +++ /dev/null @@ -1,20 +0,0 @@ -from enum import Enum - - -class OrganizationKeyScopes(Enum): - PROJECTS_READ = "projects.read" - PROJECTS_WRITE = "projects.write" - DEVKEYS_READ = "devKeys.read" - DEVKEYS_WRITE = "devKeys.write" - ORGANIZATION_KEYS_READ = "organization.keys.read" - ORGANIZATION_KEYS_WRITE = "organization.keys.write" - ORGANIZATION_INSTALLATIONS_READ = "organization.installations.read" - ORGANIZATION_INSTALLATIONS_WRITE = "organization.installations.write" - ORGANIZATION_MEMBERSHIPS_READ = "organization.memberships.read" - ORGANIZATION_MEMBERSHIPS_WRITE = "organization.memberships.write" - ORGANIZATION_READ = "organization.read" - ORGANIZATION_WRITE = "organization.write" - DOMAINS_READ = "domains.read" - DOMAINS_WRITE = "domains.write" - KEYS_READ = "keys.read" - KEYS_WRITE = "keys.write" diff --git a/appwrite/enums/proxy_rule_protocol.py b/appwrite/enums/proxy_rule_protocol.py new file mode 100644 index 00000000..9aec769f --- /dev/null +++ b/appwrite/enums/proxy_rule_protocol.py @@ -0,0 +1,6 @@ +from enum import Enum + + +class ProxyRuleProtocol(Enum): + HTTP = "http" + SMTP = "smtp" diff --git a/appwrite/models/__init__.py b/appwrite/models/__init__.py index 53aeda55..a38ce820 100644 --- a/appwrite/models/__init__.py +++ b/appwrite/models/__init__.py @@ -10,7 +10,6 @@ from .user_list import UserList from .session_list import SessionList from .identity_list import IdentityList -from .log_list import LogList from .file_list import FileList from .bucket_list import BucketList from .resource_token_list import ResourceTokenList @@ -97,7 +96,6 @@ from .row import Row from .document import Document from .presence import Presence -from .log import Log from .user import User from .algo_md5 import AlgoMd5 from .algo_sha import AlgoSha @@ -133,7 +131,6 @@ from .webhook import Webhook from .key import Key from .ephemeral_key import EphemeralKey -from .dev_key import DevKey from .mock_number import MockNumber from .o_auth2_github import OAuth2Github from .o_auth2_discord import OAuth2Discord @@ -197,6 +194,10 @@ from .policy_membership_privacy import PolicyMembershipPrivacy from .policy_mfa_factors import PolicyMfaFactors from .policy_passkey import PolicyPasskey +from .policy_deny_aliased_email import PolicyDenyAliasedEmail +from .policy_deny_disposable_email import PolicyDenyDisposableEmail +from .policy_deny_free_email import PolicyDenyFreeEmail +from .policy_deny_corporate_email import PolicyDenyCorporateEmail from .platform_web import PlatformWeb from .platform_apple import PlatformApple from .platform_android import PlatformAndroid @@ -266,10 +267,6 @@ from .organization import Organization from .dedicated_database_pitr_windows import DedicatedDatabasePITRWindows from .backup_policy import BackupPolicy -from .policy_deny_aliased_email import PolicyDenyAliasedEmail -from .policy_deny_disposable_email import PolicyDenyDisposableEmail -from .policy_deny_free_email import PolicyDenyFreeEmail -from .policy_deny_corporate_email import PolicyDenyCorporateEmail from .dedicated_database_pooler import DedicatedDatabasePooler from .postgres_extension import PostgresExtension from .program import Program @@ -277,7 +274,6 @@ from .dedicated_database_restoration_list import DedicatedDatabaseRestorationList from .dedicated_database_specification import DedicatedDatabaseSpecification from .dedicated_database_specification_list import DedicatedDatabaseSpecificationList -from .dedicated_database_specification_pricing import DedicatedDatabaseSpecificationPricing from .database_status_connections import DatabaseStatusConnections from .database_status_replica import DatabaseStatusReplica from .database_status_volume import DatabaseStatusVolume @@ -338,7 +334,6 @@ 'UserList', 'SessionList', 'IdentityList', - 'LogList', 'FileList', 'BucketList', 'ResourceTokenList', @@ -425,7 +420,6 @@ 'Row', 'Document', 'Presence', - 'Log', 'User', 'AlgoMd5', 'AlgoSha', @@ -461,7 +455,6 @@ 'Webhook', 'Key', 'EphemeralKey', - 'DevKey', 'MockNumber', 'OAuth2Github', 'OAuth2Discord', @@ -525,6 +518,10 @@ 'PolicyMembershipPrivacy', 'PolicyMfaFactors', 'PolicyPasskey', + 'PolicyDenyAliasedEmail', + 'PolicyDenyDisposableEmail', + 'PolicyDenyFreeEmail', + 'PolicyDenyCorporateEmail', 'PlatformWeb', 'PlatformApple', 'PlatformAndroid', @@ -594,10 +591,6 @@ 'Organization', 'DedicatedDatabasePITRWindows', 'BackupPolicy', - 'PolicyDenyAliasedEmail', - 'PolicyDenyDisposableEmail', - 'PolicyDenyFreeEmail', - 'PolicyDenyCorporateEmail', 'DedicatedDatabasePooler', 'PostgresExtension', 'Program', @@ -605,7 +598,6 @@ 'DedicatedDatabaseRestorationList', 'DedicatedDatabaseSpecification', 'DedicatedDatabaseSpecificationList', - 'DedicatedDatabaseSpecificationPricing', 'DatabaseStatusConnections', 'DatabaseStatusReplica', 'DatabaseStatusVolume', diff --git a/appwrite/models/account.py b/appwrite/models/account.py index 669ab5f5..f3e4eb63 100644 --- a/appwrite/models/account.py +++ b/appwrite/models/account.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast, Generic, TypeVar, Type -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .preferences import Preferences @@ -89,6 +89,45 @@ class Account(AppwriteModel, Generic[T]): impersonator: Optional[bool] = Field(default=None, alias='impersonator') impersonatoruserid: Optional[str] = Field(default=None, alias='impersonatorUserId') + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'registration' not in data: + data['registration'] = '' + if 'status' not in data: + data['status'] = True + if 'labels' not in data: + data['labels'] = [] + if 'passwordUpdate' not in data and 'passwordupdate' not in data: + data['passwordUpdate'] = '' + if 'email' not in data: + data['email'] = '' + if 'phone' not in data: + data['phone'] = '' + if 'emailVerification' not in data and 'emailverification' not in data: + data['emailVerification'] = False + if 'phoneVerification' not in data and 'phoneverification' not in data: + data['phoneVerification'] = False + if 'mfa' not in data: + data['mfa'] = False + if 'targets' not in data: + data['targets'] = [] + if 'accessedAt' not in data and 'accessedat' not in data: + data['accessedAt'] = '' + return data + @classmethod def with_data(cls, data: Dict[str, Any], model_type: Type[T] = dict) -> 'Account[T]': """Create Account instance with typed data.""" diff --git a/appwrite/models/activity_event.py b/appwrite/models/activity_event.py index d94a171c..69f3b03e 100644 --- a/appwrite/models/activity_event.py +++ b/appwrite/models/activity_event.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -99,3 +99,70 @@ class ActivityEvent(AppwriteModel): hostname: str = Field(..., alias='hostname') sdk: str = Field(..., alias='sdk') sdkversion: str = Field(..., alias='sdkVersion') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'actorType' not in data and 'actortype' not in data: + data['actorType'] = '' + if 'actorId' not in data and 'actorid' not in data: + data['actorId'] = '' + if 'actorEmail' not in data and 'actoremail' not in data: + data['actorEmail'] = '' + if 'actorName' not in data and 'actorname' not in data: + data['actorName'] = '' + if 'resourceParent' not in data and 'resourceparent' not in data: + data['resourceParent'] = '' + if 'resourceType' not in data and 'resourcetype' not in data: + data['resourceType'] = '' + if 'resourceId' not in data and 'resourceid' not in data: + data['resourceId'] = '' + if 'resource' not in data: + data['resource'] = '' + if 'event' not in data: + data['event'] = '' + if 'userAgent' not in data and 'useragent' not in data: + data['userAgent'] = '' + if 'ip' not in data: + data['ip'] = '' + if 'mode' not in data: + data['mode'] = '' + if 'country' not in data: + data['country'] = '' + if 'continentCode' not in data and 'continentcode' not in data: + data['continentCode'] = '' + if 'city' not in data: + data['city'] = '' + if 'subdivisions' not in data: + data['subdivisions'] = '' + if 'isp' not in data: + data['isp'] = '' + if 'autonomousSystemNumber' not in data and 'autonomoussystemnumber' not in data: + data['autonomousSystemNumber'] = '' + if 'autonomousSystemOrganization' not in data and 'autonomoussystemorganization' not in data: + data['autonomousSystemOrganization'] = '' + if 'connectionType' not in data and 'connectiontype' not in data: + data['connectionType'] = '' + if 'connectionUsageType' not in data and 'connectionusagetype' not in data: + data['connectionUsageType'] = '' + if 'connectionOrganization' not in data and 'connectionorganization' not in data: + data['connectionOrganization'] = '' + if 'time' not in data: + data['time'] = '' + if 'projectId' not in data and 'projectid' not in data: + data['projectId'] = '' + if 'teamId' not in data and 'teamid' not in data: + data['teamId'] = '' + if 'hostname' not in data: + data['hostname'] = '' + if 'sdk' not in data: + data['sdk'] = '' + if 'sdkVersion' not in data and 'sdkversion' not in data: + data['sdkVersion'] = '' + return data diff --git a/appwrite/models/activity_event_list.py b/appwrite/models/activity_event_list.py index 017b6ed0..ce22a31c 100644 --- a/appwrite/models/activity_event_list.py +++ b/appwrite/models/activity_event_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .activity_event import ActivityEvent @@ -19,3 +19,16 @@ class ActivityEventList(AppwriteModel): total: float = Field(..., alias='total') events: List[ActivityEvent] = Field(..., alias='events') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'events' not in data: + data['events'] = [] + return data diff --git a/appwrite/models/additional_resource.py b/appwrite/models/additional_resource.py index 4fc5c0e1..8f51ca8d 100644 --- a/appwrite/models/additional_resource.py +++ b/appwrite/models/additional_resource.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -30,3 +30,24 @@ class AdditionalResource(AppwriteModel): price: float = Field(..., alias='price') value: float = Field(..., alias='value') invoicedesc: str = Field(..., alias='invoiceDesc') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'name' not in data: + data['name'] = '' + if 'unit' not in data: + data['unit'] = '' + if 'currency' not in data: + data['currency'] = '' + if 'price' not in data: + data['price'] = 0 + if 'value' not in data: + data['value'] = 0 + if 'invoiceDesc' not in data and 'invoicedesc' not in data: + data['invoiceDesc'] = '' + return data diff --git a/appwrite/models/algo_argon2.py b/appwrite/models/algo_argon2.py index f219224e..5b87e9e7 100644 --- a/appwrite/models/algo_argon2.py +++ b/appwrite/models/algo_argon2.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class AlgoArgon2(AppwriteModel): memorycost: float = Field(..., alias='memoryCost') timecost: float = Field(..., alias='timeCost') threads: float = Field(..., alias='threads') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'type' not in data: + data['type'] = 'argon2' + if 'memoryCost' not in data and 'memorycost' not in data: + data['memoryCost'] = 0 + if 'timeCost' not in data and 'timecost' not in data: + data['timeCost'] = 0 + if 'threads' not in data: + data['threads'] = 0 + return data diff --git a/appwrite/models/algo_bcrypt.py b/appwrite/models/algo_bcrypt.py index 4fd4c9e3..25a78997 100644 --- a/appwrite/models/algo_bcrypt.py +++ b/appwrite/models/algo_bcrypt.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -15,3 +15,14 @@ class AlgoBcrypt(AppwriteModel): """ type: str = Field(..., alias='type') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'type' not in data: + data['type'] = 'bcrypt' + return data diff --git a/appwrite/models/algo_md5.py b/appwrite/models/algo_md5.py index aa7df63f..94c05b5b 100644 --- a/appwrite/models/algo_md5.py +++ b/appwrite/models/algo_md5.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -15,3 +15,14 @@ class AlgoMd5(AppwriteModel): """ type: str = Field(..., alias='type') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'type' not in data: + data['type'] = 'md5' + return data diff --git a/appwrite/models/algo_phpass.py b/appwrite/models/algo_phpass.py index 3c55ac51..9006a2c9 100644 --- a/appwrite/models/algo_phpass.py +++ b/appwrite/models/algo_phpass.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -15,3 +15,14 @@ class AlgoPhpass(AppwriteModel): """ type: str = Field(..., alias='type') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'type' not in data: + data['type'] = 'phpass' + return data diff --git a/appwrite/models/algo_scrypt.py b/appwrite/models/algo_scrypt.py index 1eb89f7c..9aa8bc05 100644 --- a/appwrite/models/algo_scrypt.py +++ b/appwrite/models/algo_scrypt.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,22 @@ class AlgoScrypt(AppwriteModel): costmemory: float = Field(..., alias='costMemory') costparallel: float = Field(..., alias='costParallel') length: float = Field(..., alias='length') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'type' not in data: + data['type'] = 'scrypt' + if 'costCpu' not in data and 'costcpu' not in data: + data['costCpu'] = 8 + if 'costMemory' not in data and 'costmemory' not in data: + data['costMemory'] = 14 + if 'costParallel' not in data and 'costparallel' not in data: + data['costParallel'] = 1 + if 'length' not in data: + data['length'] = 64 + return data diff --git a/appwrite/models/algo_scrypt_modified.py b/appwrite/models/algo_scrypt_modified.py index 76f96b48..708491ed 100644 --- a/appwrite/models/algo_scrypt_modified.py +++ b/appwrite/models/algo_scrypt_modified.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class AlgoScryptModified(AppwriteModel): salt: str = Field(..., alias='salt') saltseparator: str = Field(..., alias='saltSeparator') signerkey: str = Field(..., alias='signerKey') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'type' not in data: + data['type'] = 'scryptMod' + if 'salt' not in data: + data['salt'] = '' + if 'saltSeparator' not in data and 'saltseparator' not in data: + data['saltSeparator'] = '' + if 'signerKey' not in data and 'signerkey' not in data: + data['signerKey'] = '' + return data diff --git a/appwrite/models/algo_sha.py b/appwrite/models/algo_sha.py index e091c43f..af10ef96 100644 --- a/appwrite/models/algo_sha.py +++ b/appwrite/models/algo_sha.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -15,3 +15,14 @@ class AlgoSha(AppwriteModel): """ type: str = Field(..., alias='type') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'type' not in data: + data['type'] = 'sha' + return data diff --git a/appwrite/models/app.py b/appwrite/models/app.py index 570d8681..80a5f8f4 100644 --- a/appwrite/models/app.py +++ b/appwrite/models/app.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .app_secret import AppSecret @@ -91,3 +91,64 @@ class App(AppwriteModel): installationscopes: List[Any] = Field(..., alias='installationScopes') installationredirecturl: str = Field(..., alias='installationRedirectUrl') secrets: List[AppSecret] = Field(..., alias='secrets') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'description' not in data: + data['description'] = '' + if 'clientUri' not in data and 'clienturi' not in data: + data['clientUri'] = '' + if 'logoUri' not in data and 'logouri' not in data: + data['logoUri'] = '' + if 'privacyPolicyUrl' not in data and 'privacypolicyurl' not in data: + data['privacyPolicyUrl'] = '' + if 'termsUrl' not in data and 'termsurl' not in data: + data['termsUrl'] = '' + if 'contacts' not in data: + data['contacts'] = [] + if 'tagline' not in data: + data['tagline'] = '' + if 'tags' not in data: + data['tags'] = [] + if 'labels' not in data: + data['labels'] = [] + if 'images' not in data: + data['images'] = [] + if 'supportUrl' not in data and 'supporturl' not in data: + data['supportUrl'] = '' + if 'dataDeletionUrl' not in data and 'datadeletionurl' not in data: + data['dataDeletionUrl'] = '' + if 'redirectUris' not in data and 'redirecturis' not in data: + data['redirectUris'] = [] + if 'postLogoutRedirectUris' not in data and 'postlogoutredirecturis' not in data: + data['postLogoutRedirectUris'] = [] + if 'enabled' not in data: + data['enabled'] = True + if 'type' not in data: + data['type'] = 'confidential' + if 'deviceFlow' not in data and 'deviceflow' not in data: + data['deviceFlow'] = False + if 'teamId' not in data and 'teamid' not in data: + data['teamId'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'installationScopes' not in data and 'installationscopes' not in data: + data['installationScopes'] = [] + if 'installationRedirectUrl' not in data and 'installationredirecturl' not in data: + data['installationRedirectUrl'] = '' + if 'secrets' not in data: + data['secrets'] = [] + return data diff --git a/appwrite/models/app_installation.py b/appwrite/models/app_installation.py index 5dbfab42..c22e51d4 100644 --- a/appwrite/models/app_installation.py +++ b/appwrite/models/app_installation.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -42,3 +42,30 @@ class AppInstallation(AppwriteModel): createdbyid: str = Field(..., alias='createdById') createdbyname: str = Field(..., alias='createdByName') lastaccessedat: Optional[str] = Field(default=None, alias='lastAccessedAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'appId' not in data and 'appid' not in data: + data['appId'] = '' + if 'teamId' not in data and 'teamid' not in data: + data['teamId'] = '' + if 'scopes' not in data: + data['scopes'] = [] + if 'authorizationDetails' not in data and 'authorizationdetails' not in data: + data['authorizationDetails'] = [] + if 'createdById' not in data and 'createdbyid' not in data: + data['createdById'] = '' + if 'createdByName' not in data and 'createdbyname' not in data: + data['createdByName'] = '' + return data diff --git a/appwrite/models/app_installation_list.py b/appwrite/models/app_installation_list.py index eb06054c..de0447de 100644 --- a/appwrite/models/app_installation_list.py +++ b/appwrite/models/app_installation_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .app_installation import AppInstallation @@ -19,3 +19,16 @@ class AppInstallationList(AppwriteModel): total: float = Field(..., alias='total') installations: List[AppInstallation] = Field(..., alias='installations') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'installations' not in data: + data['installations'] = [] + return data diff --git a/appwrite/models/app_key.py b/appwrite/models/app_key.py index 8221aa10..fd4caccd 100644 --- a/appwrite/models/app_key.py +++ b/appwrite/models/app_key.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -39,3 +39,28 @@ class AppKey(AppwriteModel): createdbyid: str = Field(..., alias='createdById') createdbyname: str = Field(..., alias='createdByName') lastaccessedat: Optional[str] = Field(default=None, alias='lastAccessedAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'appId' not in data and 'appid' not in data: + data['appId'] = '' + if 'secret' not in data: + data['secret'] = '' + if 'hint' not in data: + data['hint'] = '' + if 'createdById' not in data and 'createdbyid' not in data: + data['createdById'] = '' + if 'createdByName' not in data and 'createdbyname' not in data: + data['createdByName'] = '' + return data diff --git a/appwrite/models/app_key_list.py b/appwrite/models/app_key_list.py index 32ecb90c..6e4446d7 100644 --- a/appwrite/models/app_key_list.py +++ b/appwrite/models/app_key_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .app_key import AppKey @@ -19,3 +19,16 @@ class AppKeyList(AppwriteModel): total: float = Field(..., alias='total') keys: List[AppKey] = Field(..., alias='keys') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'keys' not in data: + data['keys'] = [] + return data diff --git a/appwrite/models/app_scope.py b/appwrite/models/app_scope.py index ee295c5e..fa198925 100644 --- a/appwrite/models/app_scope.py +++ b/appwrite/models/app_scope.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,22 @@ class AppScope(AppwriteModel): type: str = Field(..., alias='type') category: str = Field(..., alias='category') deprecated: bool = Field(..., alias='deprecated') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'value' not in data: + data['value'] = '' + if 'description' not in data: + data['description'] = '' + if 'type' not in data: + data['type'] = '' + if 'category' not in data: + data['category'] = '' + if 'deprecated' not in data: + data['deprecated'] = False + return data diff --git a/appwrite/models/app_scope_list.py b/appwrite/models/app_scope_list.py index ef9484d4..653aec93 100644 --- a/appwrite/models/app_scope_list.py +++ b/appwrite/models/app_scope_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .app_scope import AppScope @@ -19,3 +19,16 @@ class AppScopeList(AppwriteModel): total: float = Field(..., alias='total') scopes: List[AppScope] = Field(..., alias='scopes') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'scopes' not in data: + data['scopes'] = [] + return data diff --git a/appwrite/models/app_secret.py b/appwrite/models/app_secret.py index 2e2b8d49..41c1052f 100644 --- a/appwrite/models/app_secret.py +++ b/appwrite/models/app_secret.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -39,3 +39,28 @@ class AppSecret(AppwriteModel): createdbyid: str = Field(..., alias='createdById') createdbyname: str = Field(..., alias='createdByName') lastaccessedat: Optional[str] = Field(default=None, alias='lastAccessedAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'appId' not in data and 'appid' not in data: + data['appId'] = '' + if 'secret' not in data: + data['secret'] = '' + if 'hint' not in data: + data['hint'] = '' + if 'createdById' not in data and 'createdbyid' not in data: + data['createdById'] = '' + if 'createdByName' not in data and 'createdbyname' not in data: + data['createdByName'] = '' + return data diff --git a/appwrite/models/app_secret_list.py b/appwrite/models/app_secret_list.py index 6b248dba..1904406c 100644 --- a/appwrite/models/app_secret_list.py +++ b/appwrite/models/app_secret_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .app_secret import AppSecret @@ -19,3 +19,16 @@ class AppSecretList(AppwriteModel): total: float = Field(..., alias='total') secrets: List[AppSecret] = Field(..., alias='secrets') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'secrets' not in data: + data['secrets'] = [] + return data diff --git a/appwrite/models/app_secret_plaintext.py b/appwrite/models/app_secret_plaintext.py index 6b7299b2..0b06766c 100644 --- a/appwrite/models/app_secret_plaintext.py +++ b/appwrite/models/app_secret_plaintext.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -39,3 +39,28 @@ class AppSecretPlaintext(AppwriteModel): createdbyid: str = Field(..., alias='createdById') createdbyname: str = Field(..., alias='createdByName') lastaccessedat: Optional[str] = Field(default=None, alias='lastAccessedAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'appId' not in data and 'appid' not in data: + data['appId'] = '' + if 'secret' not in data: + data['secret'] = '' + if 'hint' not in data: + data['hint'] = '' + if 'createdById' not in data and 'createdbyid' not in data: + data['createdById'] = '' + if 'createdByName' not in data and 'createdbyname' not in data: + data['createdByName'] = '' + return data diff --git a/appwrite/models/apps_list.py b/appwrite/models/apps_list.py index 965805a6..018b57ea 100644 --- a/appwrite/models/apps_list.py +++ b/appwrite/models/apps_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .app import App @@ -19,3 +19,16 @@ class AppsList(AppwriteModel): total: float = Field(..., alias='total') apps: List[App] = Field(..., alias='apps') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'apps' not in data: + data['apps'] = [] + return data diff --git a/appwrite/models/attribute_bigint.py b/appwrite/models/attribute_bigint.py index 5ceedae3..474812db 100644 --- a/appwrite/models/attribute_bigint.py +++ b/appwrite/models/attribute_bigint.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -46,3 +46,24 @@ class AttributeBigint(AppwriteModel): min: Optional[float] = Field(default=None, alias='min') max: Optional[float] = Field(default=None, alias='max') default: Optional[float] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/attribute_boolean.py b/appwrite/models/attribute_boolean.py index bca29adc..7ce326cb 100644 --- a/appwrite/models/attribute_boolean.py +++ b/appwrite/models/attribute_boolean.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -40,3 +40,24 @@ class AttributeBoolean(AppwriteModel): createdat: str = Field(..., alias='$createdAt') updatedat: str = Field(..., alias='$updatedAt') default: Optional[bool] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/attribute_datetime.py b/appwrite/models/attribute_datetime.py index 40c7d492..cad6726b 100644 --- a/appwrite/models/attribute_datetime.py +++ b/appwrite/models/attribute_datetime.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -43,3 +43,24 @@ class AttributeDatetime(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') format: str = Field(..., alias='format') default: Optional[str] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/attribute_email.py b/appwrite/models/attribute_email.py index 15a5dcd8..4e3c33f6 100644 --- a/appwrite/models/attribute_email.py +++ b/appwrite/models/attribute_email.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -43,3 +43,26 @@ class AttributeEmail(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') format: str = Field(..., alias='format') default: Optional[str] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'format' not in data: + data['format'] = 'email' + return data diff --git a/appwrite/models/attribute_enum.py b/appwrite/models/attribute_enum.py index 275abd2f..fdf787fc 100644 --- a/appwrite/models/attribute_enum.py +++ b/appwrite/models/attribute_enum.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -46,3 +46,28 @@ class AttributeEnum(AppwriteModel): elements: List[Any] = Field(..., alias='elements') format: str = Field(..., alias='format') default: Optional[str] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'elements' not in data: + data['elements'] = [] + if 'format' not in data: + data['format'] = 'enum' + return data diff --git a/appwrite/models/attribute_float.py b/appwrite/models/attribute_float.py index 5b989c16..209b42e8 100644 --- a/appwrite/models/attribute_float.py +++ b/appwrite/models/attribute_float.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -46,3 +46,24 @@ class AttributeFloat(AppwriteModel): min: Optional[float] = Field(default=None, alias='min') max: Optional[float] = Field(default=None, alias='max') default: Optional[float] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/attribute_integer.py b/appwrite/models/attribute_integer.py index 586d41b5..f268bb23 100644 --- a/appwrite/models/attribute_integer.py +++ b/appwrite/models/attribute_integer.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -46,3 +46,24 @@ class AttributeInteger(AppwriteModel): min: Optional[float] = Field(default=None, alias='min') max: Optional[float] = Field(default=None, alias='max') default: Optional[float] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/attribute_ip.py b/appwrite/models/attribute_ip.py index 13737149..9b334968 100644 --- a/appwrite/models/attribute_ip.py +++ b/appwrite/models/attribute_ip.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -43,3 +43,26 @@ class AttributeIp(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') format: str = Field(..., alias='format') default: Optional[str] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'format' not in data: + data['format'] = 'ip' + return data diff --git a/appwrite/models/attribute_line.py b/appwrite/models/attribute_line.py index 4e0982d4..4fbcba35 100644 --- a/appwrite/models/attribute_line.py +++ b/appwrite/models/attribute_line.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -40,3 +40,24 @@ class AttributeLine(AppwriteModel): createdat: str = Field(..., alias='$createdAt') updatedat: str = Field(..., alias='$updatedAt') default: Optional[List[Any]] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/attribute_list.py b/appwrite/models/attribute_list.py index b631a4d6..ae389072 100644 --- a/appwrite/models/attribute_list.py +++ b/appwrite/models/attribute_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .attribute_boolean import AttributeBoolean @@ -57,3 +57,16 @@ class AttributeList(AppwriteModel): AttributeString, ] ] = Field(..., alias='attributes') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'attributes' not in data: + data['attributes'] = [] + return data diff --git a/appwrite/models/attribute_longtext.py b/appwrite/models/attribute_longtext.py index cc03d9cf..fa45bfc5 100644 --- a/appwrite/models/attribute_longtext.py +++ b/appwrite/models/attribute_longtext.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -43,3 +43,24 @@ class AttributeLongtext(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') default: Optional[str] = Field(default=None, alias='default') encrypt: Optional[bool] = Field(default=None, alias='encrypt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/attribute_mediumtext.py b/appwrite/models/attribute_mediumtext.py index 40404d23..59c8ee3f 100644 --- a/appwrite/models/attribute_mediumtext.py +++ b/appwrite/models/attribute_mediumtext.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -43,3 +43,24 @@ class AttributeMediumtext(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') default: Optional[str] = Field(default=None, alias='default') encrypt: Optional[bool] = Field(default=None, alias='encrypt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/attribute_object.py b/appwrite/models/attribute_object.py index c79160bf..16e736dd 100644 --- a/appwrite/models/attribute_object.py +++ b/appwrite/models/attribute_object.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -37,3 +37,24 @@ class AttributeObject(AppwriteModel): array: Optional[bool] = Field(default=None, alias='array') createdat: str = Field(..., alias='$createdAt') updatedat: str = Field(..., alias='$updatedAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/attribute_point.py b/appwrite/models/attribute_point.py index c658fdf4..15c1d931 100644 --- a/appwrite/models/attribute_point.py +++ b/appwrite/models/attribute_point.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -40,3 +40,24 @@ class AttributePoint(AppwriteModel): createdat: str = Field(..., alias='$createdAt') updatedat: str = Field(..., alias='$updatedAt') default: Optional[List[Any]] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/attribute_polygon.py b/appwrite/models/attribute_polygon.py index 79ca2978..7d669d70 100644 --- a/appwrite/models/attribute_polygon.py +++ b/appwrite/models/attribute_polygon.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -40,3 +40,24 @@ class AttributePolygon(AppwriteModel): createdat: str = Field(..., alias='$createdAt') updatedat: str = Field(..., alias='$updatedAt') default: Optional[List[Any]] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/attribute_relationship.py b/appwrite/models/attribute_relationship.py index 540e6e88..fc549373 100644 --- a/appwrite/models/attribute_relationship.py +++ b/appwrite/models/attribute_relationship.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -55,3 +55,34 @@ class AttributeRelationship(AppwriteModel): twowaykey: str = Field(..., alias='twoWayKey') ondelete: str = Field(..., alias='onDelete') side: str = Field(..., alias='side') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'relationType' not in data and 'relationtype' not in data: + data['relationType'] = '' + if 'twoWay' not in data and 'twoway' not in data: + data['twoWay'] = False + if 'twoWayKey' not in data and 'twowaykey' not in data: + data['twoWayKey'] = '' + if 'onDelete' not in data and 'ondelete' not in data: + data['onDelete'] = 'restrict' + if 'side' not in data: + data['side'] = '' + return data diff --git a/appwrite/models/attribute_string.py b/appwrite/models/attribute_string.py index e1d101a7..7cca07a0 100644 --- a/appwrite/models/attribute_string.py +++ b/appwrite/models/attribute_string.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -46,3 +46,26 @@ class AttributeString(AppwriteModel): size: float = Field(..., alias='size') default: Optional[str] = Field(default=None, alias='default') encrypt: Optional[bool] = Field(default=None, alias='encrypt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'size' not in data: + data['size'] = 0 + return data diff --git a/appwrite/models/attribute_text.py b/appwrite/models/attribute_text.py index e819094d..b66f2a50 100644 --- a/appwrite/models/attribute_text.py +++ b/appwrite/models/attribute_text.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -43,3 +43,24 @@ class AttributeText(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') default: Optional[str] = Field(default=None, alias='default') encrypt: Optional[bool] = Field(default=None, alias='encrypt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/attribute_url.py b/appwrite/models/attribute_url.py index eb4fe4f6..50ad0ffe 100644 --- a/appwrite/models/attribute_url.py +++ b/appwrite/models/attribute_url.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -43,3 +43,26 @@ class AttributeUrl(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') format: str = Field(..., alias='format') default: Optional[str] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'format' not in data: + data['format'] = 'url' + return data diff --git a/appwrite/models/attribute_varchar.py b/appwrite/models/attribute_varchar.py index 47fdb2fb..65b806c2 100644 --- a/appwrite/models/attribute_varchar.py +++ b/appwrite/models/attribute_varchar.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -46,3 +46,26 @@ class AttributeVarchar(AppwriteModel): size: float = Field(..., alias='size') default: Optional[str] = Field(default=None, alias='default') encrypt: Optional[bool] = Field(default=None, alias='encrypt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'size' not in data: + data['size'] = 0 + return data diff --git a/appwrite/models/attribute_vector.py b/appwrite/models/attribute_vector.py index 4bcac94c..1b1d921d 100644 --- a/appwrite/models/attribute_vector.py +++ b/appwrite/models/attribute_vector.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.attribute_status import AttributeStatus @@ -40,3 +40,26 @@ class AttributeVector(AppwriteModel): createdat: str = Field(..., alias='$createdAt') updatedat: str = Field(..., alias='$updatedAt') size: float = Field(..., alias='size') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'size' not in data: + data['size'] = 0 + return data diff --git a/appwrite/models/backup_archive.py b/appwrite/models/backup_archive.py index 060ea93c..10ebf85b 100644 --- a/appwrite/models/backup_archive.py +++ b/appwrite/models/backup_archive.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,12 +18,12 @@ class BackupArchive(AppwriteModel): Archive update date in ISO 8601 format. policyid : str Archive policy ID. - size : float - Archive size in bytes. + size : Optional[float] + Archive size in bytes. Null until the size is known. status : str The status of the archive creation. Possible values: pending, processing, uploading, completed, failed, skipped. - startedat : str - The backup start time. + startedat : Optional[str] + The backup start time. Null until the backup starts. migrationid : str Migration ID. services : List[Any] @@ -40,11 +40,36 @@ class BackupArchive(AppwriteModel): createdat: str = Field(..., alias='$createdAt') updatedat: str = Field(..., alias='$updatedAt') policyid: str = Field(..., alias='policyId') - size: float = Field(..., alias='size') + size: Optional[float] = Field(default=None, alias='size') status: str = Field(..., alias='status') - startedat: str = Field(..., alias='startedAt') + startedat: Optional[str] = Field(default=None, alias='startedAt') migrationid: str = Field(..., alias='migrationId') services: List[Any] = Field(..., alias='services') resources: List[Any] = Field(..., alias='resources') resourceid: Optional[str] = Field(default=None, alias='resourceId') resourcetype: Optional[str] = Field(default=None, alias='resourceType') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'policyId' not in data and 'policyid' not in data: + data['policyId'] = '' + if 'status' not in data: + data['status'] = '' + if 'migrationId' not in data and 'migrationid' not in data: + data['migrationId'] = '' + if 'services' not in data: + data['services'] = [] + if 'resources' not in data: + data['resources'] = [] + return data diff --git a/appwrite/models/backup_archive_list.py b/appwrite/models/backup_archive_list.py index da2f9f2b..aa85f36d 100644 --- a/appwrite/models/backup_archive_list.py +++ b/appwrite/models/backup_archive_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .backup_archive import BackupArchive @@ -19,3 +19,16 @@ class BackupArchiveList(AppwriteModel): total: float = Field(..., alias='total') archives: List[BackupArchive] = Field(..., alias='archives') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'archives' not in data: + data['archives'] = [] + return data diff --git a/appwrite/models/backup_policy.py b/appwrite/models/backup_policy.py index b98ecf27..ce0118ed 100644 --- a/appwrite/models/backup_policy.py +++ b/appwrite/models/backup_policy.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -48,3 +48,32 @@ class BackupPolicy(AppwriteModel): schedule: str = Field(..., alias='schedule') type: str = Field(..., alias='type') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'name' not in data: + data['name'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'services' not in data: + data['services'] = [] + if 'resources' not in data: + data['resources'] = [] + if 'retention' not in data: + data['retention'] = 1 + if 'schedule' not in data: + data['schedule'] = '0 * * * *' + if 'type' not in data: + data['type'] = 'full' + if 'enabled' not in data: + data['enabled'] = False + return data diff --git a/appwrite/models/backup_policy_list.py b/appwrite/models/backup_policy_list.py index 3e6901a6..cf345c45 100644 --- a/appwrite/models/backup_policy_list.py +++ b/appwrite/models/backup_policy_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .backup_policy import BackupPolicy @@ -19,3 +19,16 @@ class BackupPolicyList(AppwriteModel): total: float = Field(..., alias='total') policies: List[BackupPolicy] = Field(..., alias='policies') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'policies' not in data: + data['policies'] = [] + return data diff --git a/appwrite/models/backup_restoration.py b/appwrite/models/backup_restoration.py index c00fe712..ba0e9d2f 100644 --- a/appwrite/models/backup_restoration.py +++ b/appwrite/models/backup_restoration.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -22,16 +22,16 @@ class BackupRestoration(AppwriteModel): Backup policy ID. status : str The status of the restoration. Possible values: pending, downloading, processing, completed, failed. - startedat : str - The backup start time. + startedat : Optional[str] + The restoration start time. Null until the restoration starts. migrationid : str Migration ID. services : List[Any] The services that are backed up by this policy. resources : List[Any] The resources that are backed up by this policy. - options : str - Optional data in key-value object. + options : Dict[str, Any] + Restoration options as a key-value object. """ id: str = Field(..., alias='$id') @@ -40,8 +40,37 @@ class BackupRestoration(AppwriteModel): archiveid: str = Field(..., alias='archiveId') policyid: str = Field(..., alias='policyId') status: str = Field(..., alias='status') - startedat: str = Field(..., alias='startedAt') + startedat: Optional[str] = Field(default=None, alias='startedAt') migrationid: str = Field(..., alias='migrationId') services: List[Any] = Field(..., alias='services') resources: List[Any] = Field(..., alias='resources') - options: str = Field(..., alias='options') + options: Dict[str, Any] = Field(..., alias='options') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'archiveId' not in data and 'archiveid' not in data: + data['archiveId'] = '' + if 'policyId' not in data and 'policyid' not in data: + data['policyId'] = '' + if 'status' not in data: + data['status'] = '' + if 'migrationId' not in data and 'migrationid' not in data: + data['migrationId'] = '' + if 'services' not in data: + data['services'] = [] + if 'resources' not in data: + data['resources'] = [] + if 'options' not in data: + data['options'] = {} + return data diff --git a/appwrite/models/backup_restoration_list.py b/appwrite/models/backup_restoration_list.py index 53e57497..efcf9638 100644 --- a/appwrite/models/backup_restoration_list.py +++ b/appwrite/models/backup_restoration_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .backup_restoration import BackupRestoration @@ -19,3 +19,16 @@ class BackupRestorationList(AppwriteModel): total: float = Field(..., alias='total') restorations: List[BackupRestoration] = Field(..., alias='restorations') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'restorations' not in data: + data['restorations'] = [] + return data diff --git a/appwrite/models/billing_plan.py b/appwrite/models/billing_plan.py index e63f0dbf..545e198b 100644 --- a/appwrite/models/billing_plan.py +++ b/appwrite/models/billing_plan.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .usage_billing_plan import UsageBillingPlan @@ -43,7 +43,7 @@ class BillingPlan(AppwriteModel): Webhooks wafrules : float Maximum WAF rules per project - environments : Optional[float] + environments : float Maximum environments per project. 0 when the plan does not offer environments. projects : float Projects @@ -99,8 +99,8 @@ class BillingPlan(AppwriteModel): Number of days of console inactivity before a project is paused. 0 means pausing is disabled. alertlimit : float Alert threshold percentage - usage : UsageBillingPlan - Additional resources + usage : Optional[UsageBillingPlan] + Additional resources. Null when the plan does not support usage billing. addons : BillingPlanAddon Addons budgetcapenabled : bool @@ -182,7 +182,7 @@ class BillingPlan(AppwriteModel): members: Optional[float] = Field(default=None, alias='members') webhooks: float = Field(..., alias='webhooks') wafrules: float = Field(..., alias='wafRules') - environments: Optional[float] = Field(default=None, alias='environments') + environments: float = Field(..., alias='environments') projects: float = Field(..., alias='projects') platforms: float = Field(..., alias='platforms') users: float = Field(..., alias='users') @@ -210,7 +210,7 @@ class BillingPlan(AppwriteModel): usageaggregateonlymetrics: Optional[List[Any]] = Field(default=None, alias='usageAggregateOnlyMetrics') projectinactivitydays: float = Field(..., alias='projectInactivityDays') alertlimit: float = Field(..., alias='alertLimit') - usage: UsageBillingPlan = Field(..., alias='usage') + usage: Optional[UsageBillingPlan] = Field(default=None, alias='usage') addons: BillingPlanAddon = Field(..., alias='addons') budgetcapenabled: bool = Field(..., alias='budgetCapEnabled') customsmtp: bool = Field(..., alias='customSmtp') @@ -244,3 +244,134 @@ class BillingPlan(AppwriteModel): program: Optional[Program] = Field(default=None, alias='program') databasecomputecredit: float = Field(..., alias='databaseComputeCredit') dedicateddatabases: Optional[BillingPlanDedicatedDatabaseLimits] = Field(default=None, alias='dedicatedDatabases') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'name' not in data: + data['name'] = '' + if 'desc' not in data: + data['desc'] = '' + if 'order' not in data: + data['order'] = 0 + if 'price' not in data: + data['price'] = 0 + if 'trial' not in data: + data['trial'] = 0 + if 'bandwidth' not in data: + data['bandwidth'] = 0 + if 'storage' not in data: + data['storage'] = 0 + if 'imageTransformations' not in data and 'imagetransformations' not in data: + data['imageTransformations'] = 0 + if 'screenshotsGenerated' not in data and 'screenshotsgenerated' not in data: + data['screenshotsGenerated'] = 0 + if 'webhooks' not in data: + data['webhooks'] = 0 + if 'wafRules' not in data and 'wafrules' not in data: + data['wafRules'] = 0 + if 'environments' not in data: + data['environments'] = 0 + if 'projects' not in data: + data['projects'] = 0 + if 'platforms' not in data: + data['platforms'] = 0 + if 'users' not in data: + data['users'] = 0 + if 'teams' not in data: + data['teams'] = 0 + if 'databases' not in data: + data['databases'] = 0 + if 'databasesReads' not in data and 'databasesreads' not in data: + data['databasesReads'] = 0 + if 'databasesWrites' not in data and 'databaseswrites' not in data: + data['databasesWrites'] = 0 + if 'databasesBatchSize' not in data and 'databasesbatchsize' not in data: + data['databasesBatchSize'] = 0 + if 'buckets' not in data: + data['buckets'] = 0 + if 'fileSize' not in data and 'filesize' not in data: + data['fileSize'] = 0 + if 'functions' not in data: + data['functions'] = 0 + if 'sites' not in data: + data['sites'] = 0 + if 'executions' not in data: + data['executions'] = 0 + if 'executionsRetentionCount' not in data and 'executionsretentioncount' not in data: + data['executionsRetentionCount'] = 1000 + if 'GBHours' not in data and 'gbhours' not in data: + data['GBHours'] = 0 + if 'realtime' not in data: + data['realtime'] = 0 + if 'realtimeMessages' not in data and 'realtimemessages' not in data: + data['realtimeMessages'] = 0 + if 'messages' not in data: + data['messages'] = 0 + if 'topics' not in data: + data['topics'] = 0 + if 'authPhone' not in data and 'authphone' not in data: + data['authPhone'] = 0 + if 'domains' not in data: + data['domains'] = 0 + if 'usageLogs' not in data and 'usagelogs' not in data: + data['usageLogs'] = 0 + if 'projectInactivityDays' not in data and 'projectinactivitydays' not in data: + data['projectInactivityDays'] = 0 + if 'alertLimit' not in data and 'alertlimit' not in data: + data['alertLimit'] = 80 + if 'budgetCapEnabled' not in data and 'budgetcapenabled' not in data: + data['budgetCapEnabled'] = False + if 'customSmtp' not in data and 'customsmtp' not in data: + data['customSmtp'] = False + if 'emailBranding' not in data and 'emailbranding' not in data: + data['emailBranding'] = False + if 'requiresPaymentMethod' not in data and 'requirespaymentmethod' not in data: + data['requiresPaymentMethod'] = True + if 'requiresBillingAddress' not in data and 'requiresbillingaddress' not in data: + data['requiresBillingAddress'] = False + if 'isAvailable' not in data and 'isavailable' not in data: + data['isAvailable'] = True + if 'selfService' not in data and 'selfservice' not in data: + data['selfService'] = True + if 'premiumSupport' not in data and 'premiumsupport' not in data: + data['premiumSupport'] = True + if 'budgeting' not in data: + data['budgeting'] = True + if 'supportsMockNumbers' not in data and 'supportsmocknumbers' not in data: + data['supportsMockNumbers'] = True + if 'supportsOrganizationRoles' not in data and 'supportsorganizationroles' not in data: + data['supportsOrganizationRoles'] = True + if 'supportsCredits' not in data and 'supportscredits' not in data: + data['supportsCredits'] = False + if 'supportsDedicatedDatabases' not in data and 'supportsdedicateddatabases' not in data: + data['supportsDedicatedDatabases'] = False + if 'supportsDisposableEmailValidation' not in data and 'supportsdisposableemailvalidation' not in data: + data['supportsDisposableEmailValidation'] = False + if 'supportsCanonicalEmailValidation' not in data and 'supportscanonicalemailvalidation' not in data: + data['supportsCanonicalEmailValidation'] = False + if 'supportsFreeEmailValidation' not in data and 'supportsfreeemailvalidation' not in data: + data['supportsFreeEmailValidation'] = False + if 'supportsCorporateEmailValidation' not in data and 'supportscorporateemailvalidation' not in data: + data['supportsCorporateEmailValidation'] = False + if 'supportsProjectSpecificRoles' not in data and 'supportsprojectspecificroles' not in data: + data['supportsProjectSpecificRoles'] = False + if 'usagePerProject' not in data and 'usageperproject' not in data: + data['usagePerProject'] = True + if 'deploymentSize' not in data and 'deploymentsize' not in data: + data['deploymentSize'] = 0 + if 'buildSize' not in data and 'buildsize' not in data: + data['buildSize'] = 0 + if 'functionsIntervalMinimum' not in data and 'functionsintervalminimum' not in data: + data['functionsIntervalMinimum'] = 0 + if 'databasesAllowEncrypt' not in data and 'databasesallowencrypt' not in data: + data['databasesAllowEncrypt'] = False + if 'databaseComputeCredit' not in data and 'databasecomputecredit' not in data: + data['databaseComputeCredit'] = 0 + return data diff --git a/appwrite/models/billing_plan_addon_details.py b/appwrite/models/billing_plan_addon_details.py index 8d7591f1..e499f40c 100644 --- a/appwrite/models/billing_plan_addon_details.py +++ b/appwrite/models/billing_plan_addon_details.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -36,3 +36,26 @@ class BillingPlanAddonDetails(AppwriteModel): price: float = Field(..., alias='price') value: float = Field(..., alias='value') invoicedesc: str = Field(..., alias='invoiceDesc') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'supported' not in data: + data['supported'] = False + if 'planIncluded' not in data and 'planincluded' not in data: + data['planIncluded'] = 0 + if 'limit' not in data: + data['limit'] = 0 + if 'type' not in data: + data['type'] = 'numeric' + if 'price' not in data: + data['price'] = 0 + if 'value' not in data: + data['value'] = 0 + if 'invoiceDesc' not in data and 'invoicedesc' not in data: + data['invoiceDesc'] = '' + return data diff --git a/appwrite/models/billing_plan_supported_addons.py b/appwrite/models/billing_plan_supported_addons.py index 756a37e1..39ef9544 100644 --- a/appwrite/models/billing_plan_supported_addons.py +++ b/appwrite/models/billing_plan_supported_addons.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -21,3 +21,18 @@ class BillingPlanSupportedAddons(AppwriteModel): baa: bool = Field(..., alias='baa') premiumgeodb: bool = Field(..., alias='premiumGeoDB') premiumgeodborg: bool = Field(..., alias='premiumGeoDBOrg') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'baa' not in data: + data['baa'] = False + if 'premiumGeoDB' not in data and 'premiumgeodb' not in data: + data['premiumGeoDB'] = False + if 'premiumGeoDBOrg' not in data and 'premiumgeodborg' not in data: + data['premiumGeoDBOrg'] = False + return data diff --git a/appwrite/models/block.py b/appwrite/models/block.py index fdc801cc..94669353 100644 --- a/appwrite/models/block.py +++ b/appwrite/models/block.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,30 +18,29 @@ class Block(AppwriteModel): Resource identifier that is blocked mode : str Block mode. full blocks reads and writes; readOnly blocks writes only. - reason : Optional[str] - Reason for the block. Can be null if no reason was provided. expiredat : Optional[str] Block expiration date in ISO 8601 format. Can be null if the block does not expire. - projectname : str - Name of the project this block applies to. - region : str - Region of the project this block applies to. - organizationname : str - Name of the organization that owns the project. - organizationid : str - ID of the organization that owns the project. - billingplan : str - Billing plan of the organization that owns the project. """ createdat: str = Field(..., alias='$createdAt') resourcetype: str = Field(..., alias='resourceType') resourceid: str = Field(..., alias='resourceId') mode: str = Field(..., alias='mode') - reason: Optional[str] = Field(default=None, alias='reason') expiredat: Optional[str] = Field(default=None, alias='expiredAt') - projectname: str = Field(..., alias='projectName') - region: str = Field(..., alias='region') - organizationname: str = Field(..., alias='organizationName') - organizationid: str = Field(..., alias='organizationId') - billingplan: str = Field(..., alias='billingPlan') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if 'resourceType' not in data and 'resourcetype' not in data: + data['resourceType'] = '' + if 'resourceId' not in data and 'resourceid' not in data: + data['resourceId'] = '' + if 'mode' not in data: + data['mode'] = 'full' + return data diff --git a/appwrite/models/bucket.py b/appwrite/models/bucket.py index 7aafabf8..7718a57d 100644 --- a/appwrite/models/bucket.py +++ b/appwrite/models/bucket.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -54,3 +54,40 @@ class Bucket(AppwriteModel): antivirus: bool = Field(..., alias='antivirus') transformations: bool = Field(..., alias='transformations') totalsize: float = Field(..., alias='totalSize') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if '$permissions' not in data and 'permissions' not in data: + data['$permissions'] = [] + if 'fileSecurity' not in data and 'filesecurity' not in data: + data['fileSecurity'] = False + if 'name' not in data: + data['name'] = '' + if 'enabled' not in data: + data['enabled'] = True + if 'maximumFileSize' not in data and 'maximumfilesize' not in data: + data['maximumFileSize'] = 0 + if 'allowedFileExtensions' not in data and 'allowedfileextensions' not in data: + data['allowedFileExtensions'] = [] + if 'compression' not in data: + data['compression'] = '' + if 'encryption' not in data: + data['encryption'] = True + if 'antivirus' not in data: + data['antivirus'] = True + if 'transformations' not in data: + data['transformations'] = True + if 'totalSize' not in data and 'totalsize' not in data: + data['totalSize'] = 0 + return data diff --git a/appwrite/models/bucket_list.py b/appwrite/models/bucket_list.py index 3191bd45..32947b35 100644 --- a/appwrite/models/bucket_list.py +++ b/appwrite/models/bucket_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .bucket import Bucket @@ -19,3 +19,16 @@ class BucketList(AppwriteModel): total: float = Field(..., alias='total') buckets: List[Bucket] = Field(..., alias='buckets') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'buckets' not in data: + data['buckets'] = [] + return data diff --git a/appwrite/models/collection.py b/appwrite/models/collection.py index ab344ebc..419ec48a 100644 --- a/appwrite/models/collection.py +++ b/appwrite/models/collection.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .attribute_boolean import AttributeBoolean @@ -88,3 +88,36 @@ class Collection(AppwriteModel): indexes: List[Index] = Field(..., alias='indexes') bytesmax: float = Field(..., alias='bytesMax') bytesused: float = Field(..., alias='bytesUsed') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if '$permissions' not in data and 'permissions' not in data: + data['$permissions'] = [] + if 'databaseId' not in data and 'databaseid' not in data: + data['databaseId'] = '' + if 'name' not in data: + data['name'] = '' + if 'enabled' not in data: + data['enabled'] = True + if 'documentSecurity' not in data and 'documentsecurity' not in data: + data['documentSecurity'] = False + if 'attributes' not in data: + data['attributes'] = [] + if 'indexes' not in data: + data['indexes'] = [] + if 'bytesMax' not in data and 'bytesmax' not in data: + data['bytesMax'] = 0 + if 'bytesUsed' not in data and 'bytesused' not in data: + data['bytesUsed'] = 0 + return data diff --git a/appwrite/models/collection_list.py b/appwrite/models/collection_list.py index 87db81ed..167783f4 100644 --- a/appwrite/models/collection_list.py +++ b/appwrite/models/collection_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .collection import Collection @@ -19,3 +19,16 @@ class CollectionList(AppwriteModel): total: float = Field(..., alias='total') collections: List[Collection] = Field(..., alias='collections') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'collections' not in data: + data['collections'] = [] + return data diff --git a/appwrite/models/column_bigint.py b/appwrite/models/column_bigint.py index e69b46f3..b2fa8225 100644 --- a/appwrite/models/column_bigint.py +++ b/appwrite/models/column_bigint.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -46,3 +46,24 @@ class ColumnBigint(AppwriteModel): min: Optional[float] = Field(default=None, alias='min') max: Optional[float] = Field(default=None, alias='max') default: Optional[float] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/column_boolean.py b/appwrite/models/column_boolean.py index 0c760ff3..33ebd132 100644 --- a/appwrite/models/column_boolean.py +++ b/appwrite/models/column_boolean.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -40,3 +40,24 @@ class ColumnBoolean(AppwriteModel): createdat: str = Field(..., alias='$createdAt') updatedat: str = Field(..., alias='$updatedAt') default: Optional[bool] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/column_datetime.py b/appwrite/models/column_datetime.py index eb06acff..46c1d04a 100644 --- a/appwrite/models/column_datetime.py +++ b/appwrite/models/column_datetime.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -43,3 +43,24 @@ class ColumnDatetime(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') format: str = Field(..., alias='format') default: Optional[str] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/column_email.py b/appwrite/models/column_email.py index 2cb80040..68094615 100644 --- a/appwrite/models/column_email.py +++ b/appwrite/models/column_email.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -43,3 +43,26 @@ class ColumnEmail(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') format: str = Field(..., alias='format') default: Optional[str] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'format' not in data: + data['format'] = 'email' + return data diff --git a/appwrite/models/column_enum.py b/appwrite/models/column_enum.py index cd3a3348..3dd815af 100644 --- a/appwrite/models/column_enum.py +++ b/appwrite/models/column_enum.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -46,3 +46,28 @@ class ColumnEnum(AppwriteModel): elements: List[Any] = Field(..., alias='elements') format: str = Field(..., alias='format') default: Optional[str] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'elements' not in data: + data['elements'] = [] + if 'format' not in data: + data['format'] = 'enum' + return data diff --git a/appwrite/models/column_float.py b/appwrite/models/column_float.py index c229043c..aa089000 100644 --- a/appwrite/models/column_float.py +++ b/appwrite/models/column_float.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -46,3 +46,24 @@ class ColumnFloat(AppwriteModel): min: Optional[float] = Field(default=None, alias='min') max: Optional[float] = Field(default=None, alias='max') default: Optional[float] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/column_index.py b/appwrite/models/column_index.py index 91ba84b7..54419edf 100644 --- a/appwrite/models/column_index.py +++ b/appwrite/models/column_index.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -42,3 +42,30 @@ class ColumnIndex(AppwriteModel): columns: List[Any] = Field(..., alias='columns') lengths: List[Any] = Field(..., alias='lengths') orders: Optional[List[Any]] = Field(default=None, alias='orders') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'status' not in data: + data['status'] = '' + if 'error' not in data: + data['error'] = '' + if 'columns' not in data: + data['columns'] = [] + if 'lengths' not in data: + data['lengths'] = [] + return data diff --git a/appwrite/models/column_index_list.py b/appwrite/models/column_index_list.py index 3e3cdfdb..78df3b87 100644 --- a/appwrite/models/column_index_list.py +++ b/appwrite/models/column_index_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .column_index import ColumnIndex @@ -19,3 +19,16 @@ class ColumnIndexList(AppwriteModel): total: float = Field(..., alias='total') indexes: List[ColumnIndex] = Field(..., alias='indexes') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'indexes' not in data: + data['indexes'] = [] + return data diff --git a/appwrite/models/column_integer.py b/appwrite/models/column_integer.py index f5282bc7..9ad8fbd4 100644 --- a/appwrite/models/column_integer.py +++ b/appwrite/models/column_integer.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -46,3 +46,24 @@ class ColumnInteger(AppwriteModel): min: Optional[float] = Field(default=None, alias='min') max: Optional[float] = Field(default=None, alias='max') default: Optional[float] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/column_ip.py b/appwrite/models/column_ip.py index d9c006ae..fe5de6b6 100644 --- a/appwrite/models/column_ip.py +++ b/appwrite/models/column_ip.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -43,3 +43,26 @@ class ColumnIp(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') format: str = Field(..., alias='format') default: Optional[str] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'format' not in data: + data['format'] = 'ip' + return data diff --git a/appwrite/models/column_line.py b/appwrite/models/column_line.py index a7451f5d..0216047f 100644 --- a/appwrite/models/column_line.py +++ b/appwrite/models/column_line.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -40,3 +40,24 @@ class ColumnLine(AppwriteModel): createdat: str = Field(..., alias='$createdAt') updatedat: str = Field(..., alias='$updatedAt') default: Optional[List[Any]] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/column_list.py b/appwrite/models/column_list.py index bc464e88..8c362871 100644 --- a/appwrite/models/column_list.py +++ b/appwrite/models/column_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .column_boolean import ColumnBoolean @@ -57,3 +57,16 @@ class ColumnList(AppwriteModel): ColumnString, ] ] = Field(..., alias='columns') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'columns' not in data: + data['columns'] = [] + return data diff --git a/appwrite/models/column_longtext.py b/appwrite/models/column_longtext.py index 6df8a506..ce3585fd 100644 --- a/appwrite/models/column_longtext.py +++ b/appwrite/models/column_longtext.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -43,3 +43,24 @@ class ColumnLongtext(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') default: Optional[str] = Field(default=None, alias='default') encrypt: Optional[bool] = Field(default=None, alias='encrypt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/column_mediumtext.py b/appwrite/models/column_mediumtext.py index 6c6f0235..31717475 100644 --- a/appwrite/models/column_mediumtext.py +++ b/appwrite/models/column_mediumtext.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -43,3 +43,24 @@ class ColumnMediumtext(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') default: Optional[str] = Field(default=None, alias='default') encrypt: Optional[bool] = Field(default=None, alias='encrypt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/column_point.py b/appwrite/models/column_point.py index 3ca81d01..0217c08e 100644 --- a/appwrite/models/column_point.py +++ b/appwrite/models/column_point.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -40,3 +40,24 @@ class ColumnPoint(AppwriteModel): createdat: str = Field(..., alias='$createdAt') updatedat: str = Field(..., alias='$updatedAt') default: Optional[List[Any]] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/column_polygon.py b/appwrite/models/column_polygon.py index 172d7628..3bcc61c9 100644 --- a/appwrite/models/column_polygon.py +++ b/appwrite/models/column_polygon.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -40,3 +40,24 @@ class ColumnPolygon(AppwriteModel): createdat: str = Field(..., alias='$createdAt') updatedat: str = Field(..., alias='$updatedAt') default: Optional[List[Any]] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/column_relationship.py b/appwrite/models/column_relationship.py index 32a6da3a..5b1f96b9 100644 --- a/appwrite/models/column_relationship.py +++ b/appwrite/models/column_relationship.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -55,3 +55,34 @@ class ColumnRelationship(AppwriteModel): twowaykey: str = Field(..., alias='twoWayKey') ondelete: str = Field(..., alias='onDelete') side: str = Field(..., alias='side') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'relationType' not in data and 'relationtype' not in data: + data['relationType'] = '' + if 'twoWay' not in data and 'twoway' not in data: + data['twoWay'] = False + if 'twoWayKey' not in data and 'twowaykey' not in data: + data['twoWayKey'] = '' + if 'onDelete' not in data and 'ondelete' not in data: + data['onDelete'] = 'restrict' + if 'side' not in data: + data['side'] = '' + return data diff --git a/appwrite/models/column_string.py b/appwrite/models/column_string.py index 664904d2..c8d5efcb 100644 --- a/appwrite/models/column_string.py +++ b/appwrite/models/column_string.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -46,3 +46,26 @@ class ColumnString(AppwriteModel): size: float = Field(..., alias='size') default: Optional[str] = Field(default=None, alias='default') encrypt: Optional[bool] = Field(default=None, alias='encrypt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'size' not in data: + data['size'] = 0 + return data diff --git a/appwrite/models/column_text.py b/appwrite/models/column_text.py index a171fe08..29ea6f5b 100644 --- a/appwrite/models/column_text.py +++ b/appwrite/models/column_text.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -43,3 +43,24 @@ class ColumnText(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') default: Optional[str] = Field(default=None, alias='default') encrypt: Optional[bool] = Field(default=None, alias='encrypt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/column_url.py b/appwrite/models/column_url.py index fb1269c0..bb51776b 100644 --- a/appwrite/models/column_url.py +++ b/appwrite/models/column_url.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -43,3 +43,26 @@ class ColumnUrl(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') format: str = Field(..., alias='format') default: Optional[str] = Field(default=None, alias='default') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'format' not in data: + data['format'] = 'url' + return data diff --git a/appwrite/models/column_varchar.py b/appwrite/models/column_varchar.py index c6ec96c5..113ca34f 100644 --- a/appwrite/models/column_varchar.py +++ b/appwrite/models/column_varchar.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.column_status import ColumnStatus @@ -46,3 +46,26 @@ class ColumnVarchar(AppwriteModel): size: float = Field(..., alias='size') default: Optional[str] = Field(default=None, alias='default') encrypt: Optional[bool] = Field(default=None, alias='encrypt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'required' not in data: + data['required'] = False + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'size' not in data: + data['size'] = 0 + return data diff --git a/appwrite/models/continent.py b/appwrite/models/continent.py index ebc9026c..81dc6132 100644 --- a/appwrite/models/continent.py +++ b/appwrite/models/continent.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class Continent(AppwriteModel): name: str = Field(..., alias='name') code: str = Field(..., alias='code') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'name' not in data: + data['name'] = '' + if 'code' not in data: + data['code'] = '' + return data diff --git a/appwrite/models/continent_list.py b/appwrite/models/continent_list.py index a6f30050..cf69936f 100644 --- a/appwrite/models/continent_list.py +++ b/appwrite/models/continent_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .continent import Continent @@ -19,3 +19,16 @@ class ContinentList(AppwriteModel): total: float = Field(..., alias='total') continents: List[Continent] = Field(..., alias='continents') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'continents' not in data: + data['continents'] = [] + return data diff --git a/appwrite/models/country.py b/appwrite/models/country.py index 5c40de11..5938df75 100644 --- a/appwrite/models/country.py +++ b/appwrite/models/country.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class Country(AppwriteModel): name: str = Field(..., alias='name') code: str = Field(..., alias='code') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'name' not in data: + data['name'] = '' + if 'code' not in data: + data['code'] = '' + return data diff --git a/appwrite/models/country_list.py b/appwrite/models/country_list.py index 73dda289..14922fd9 100644 --- a/appwrite/models/country_list.py +++ b/appwrite/models/country_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .country import Country @@ -19,3 +19,16 @@ class CountryList(AppwriteModel): total: float = Field(..., alias='total') countries: List[Country] = Field(..., alias='countries') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'countries' not in data: + data['countries'] = [] + return data diff --git a/appwrite/models/currency.py b/appwrite/models/currency.py index 52eacdda..83f45e3b 100644 --- a/appwrite/models/currency.py +++ b/appwrite/models/currency.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -33,3 +33,26 @@ class Currency(AppwriteModel): rounding: float = Field(..., alias='rounding') code: str = Field(..., alias='code') nameplural: str = Field(..., alias='namePlural') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'symbol' not in data: + data['symbol'] = '' + if 'name' not in data: + data['name'] = '' + if 'symbolNative' not in data and 'symbolnative' not in data: + data['symbolNative'] = '' + if 'decimalDigits' not in data and 'decimaldigits' not in data: + data['decimalDigits'] = 0 + if 'rounding' not in data: + data['rounding'] = 0 + if 'code' not in data: + data['code'] = '' + if 'namePlural' not in data and 'nameplural' not in data: + data['namePlural'] = '' + return data diff --git a/appwrite/models/currency_list.py b/appwrite/models/currency_list.py index c4022da6..bf3e3469 100644 --- a/appwrite/models/currency_list.py +++ b/appwrite/models/currency_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .currency import Currency @@ -19,3 +19,16 @@ class CurrencyList(AppwriteModel): total: float = Field(..., alias='total') currencies: List[Currency] = Field(..., alias='currencies') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'currencies' not in data: + data['currencies'] = [] + return data diff --git a/appwrite/models/database.py b/appwrite/models/database.py index 031d2e6c..931cb68d 100644 --- a/appwrite/models/database.py +++ b/appwrite/models/database.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.database_type import DatabaseType @@ -37,7 +37,7 @@ class Database(AppwriteModel): error : Optional[str] Error message when the dedicated backing failed. Null when the database has no dedicated backing or has not failed. containerstatus : Optional[str] - Container status of the dedicated backing: active or inactive. Null when the database has no dedicated backing or the runtime has not reported one. + Container status of the dedicated backing: active, inactive, or failed (a wake was declined because the backing namespace is gone). Null when the database has no dedicated backing or the runtime has not reported one. lifecyclestate : Optional[str] Idle-lifecycle state of the dedicated backing: active, warm, cold, or hibernated. Null when the database has no dedicated backing or the runtime has not reported one. policies : Optional[List[BackupPolicy]] @@ -61,3 +61,24 @@ class Database(AppwriteModel): lifecyclestate: Optional[str] = Field(default=None, alias='lifecycleState') policies: Optional[List[BackupPolicy]] = Field(default=None, alias='policies') archives: Optional[List[BackupArchive]] = Field(default=None, alias='archives') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'name' not in data: + data['name'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'enabled' not in data: + data['enabled'] = True + if 'type' not in data: + data['type'] = 'legacy' + return data diff --git a/appwrite/models/database_list.py b/appwrite/models/database_list.py index a7d726c2..800f316d 100644 --- a/appwrite/models/database_list.py +++ b/appwrite/models/database_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .database import Database @@ -19,3 +19,16 @@ class DatabaseList(AppwriteModel): total: float = Field(..., alias='total') databases: List[Database] = Field(..., alias='databases') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'databases' not in data: + data['databases'] = [] + return data diff --git a/appwrite/models/database_migration.py b/appwrite/models/database_migration.py index a0acc2f2..9342c20b 100644 --- a/appwrite/models/database_migration.py +++ b/appwrite/models/database_migration.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -63,3 +63,46 @@ class DatabaseMigration(AppwriteModel): autocutover: bool = Field(..., alias='autoCutover') cutoverrequested: bool = Field(..., alias='cutoverRequested') paused: bool = Field(..., alias='paused') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'projectId' not in data and 'projectid' not in data: + data['projectId'] = '' + if 'databaseId' not in data and 'databaseid' not in data: + data['databaseId'] = '' + if 'specification' not in data: + data['specification'] = '' + if 'phase' not in data: + data['phase'] = 'pending' + if 'attempt' not in data: + data['attempt'] = 0 + if 'lastError' not in data and 'lasterror' not in data: + data['lastError'] = '' + if 'lagDocuments' not in data and 'lagdocuments' not in data: + data['lagDocuments'] = 0 + if 'changelogWatermark' not in data and 'changelogwatermark' not in data: + data['changelogWatermark'] = 0 + if 'verifiedAt' not in data and 'verifiedat' not in data: + data['verifiedAt'] = '' + if 'cutoverAt' not in data and 'cutoverat' not in data: + data['cutoverAt'] = '' + if 'soakUntil' not in data and 'soakuntil' not in data: + data['soakUntil'] = '' + if 'autoCutover' not in data and 'autocutover' not in data: + data['autoCutover'] = True + if 'cutoverRequested' not in data and 'cutoverrequested' not in data: + data['cutoverRequested'] = False + if 'paused' not in data: + data['paused'] = False + return data diff --git a/appwrite/models/database_migration_list.py b/appwrite/models/database_migration_list.py index a8b956c4..014ddc2a 100644 --- a/appwrite/models/database_migration_list.py +++ b/appwrite/models/database_migration_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .database_migration import DatabaseMigration @@ -19,3 +19,16 @@ class DatabaseMigrationList(AppwriteModel): total: float = Field(..., alias='total') migrations: List[DatabaseMigration] = Field(..., alias='migrations') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'migrations' not in data: + data['migrations'] = [] + return data diff --git a/appwrite/models/database_status.py b/appwrite/models/database_status.py index 06a7cfd4..52c14ccf 100644 --- a/appwrite/models/database_status.py +++ b/appwrite/models/database_status.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .database_status_connections import DatabaseStatusConnections @@ -23,8 +23,8 @@ class DatabaseStatus(AppwriteModel): Database engine version. uptime : float Database uptime in seconds. - connections : DatabaseStatusConnections - Connection statistics. + connections : Optional[DatabaseStatusConnections] + Connection statistics. Null when the database has not been probed. syncmode : str Requested replication sync mode. Possible values: async, sync, quorum. Compare with effectiveSyncMode for what the primary is enforcing. effectivesyncmode : Optional[str] @@ -48,7 +48,7 @@ class DatabaseStatus(AppwriteModel): engine: str = Field(..., alias='engine') version: str = Field(..., alias='version') uptime: float = Field(..., alias='uptime') - connections: DatabaseStatusConnections = Field(..., alias='connections') + connections: Optional[DatabaseStatusConnections] = Field(default=None, alias='connections') syncmode: str = Field(..., alias='syncMode') effectivesyncmode: Optional[str] = Field(default=None, alias='effectiveSyncMode') syncdegraded: bool = Field(..., alias='syncDegraded') @@ -57,3 +57,34 @@ class DatabaseStatus(AppwriteModel): syncstateconfirmed: Optional[bool] = Field(default=None, alias='syncStateConfirmed') replicas: List[DatabaseStatusReplica] = Field(..., alias='replicas') volumes: List[DatabaseStatusVolume] = Field(..., alias='volumes') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'health' not in data: + data['health'] = 'unknown' + if 'ready' not in data: + data['ready'] = False + if 'engine' not in data: + data['engine'] = 'postgresql' + if 'version' not in data: + data['version'] = '' + if 'uptime' not in data: + data['uptime'] = 0 + if 'syncMode' not in data and 'syncmode' not in data: + data['syncMode'] = 'async' + if 'syncDegraded' not in data and 'syncdegraded' not in data: + data['syncDegraded'] = False + if 'syncAcknowledgements' not in data and 'syncacknowledgements' not in data: + data['syncAcknowledgements'] = 0 + if 'syncStandbyCount' not in data and 'syncstandbycount' not in data: + data['syncStandbyCount'] = 0 + if 'replicas' not in data: + data['replicas'] = [] + if 'volumes' not in data: + data['volumes'] = [] + return data diff --git a/appwrite/models/database_status_connections.py b/appwrite/models/database_status_connections.py index 1cce2821..caf927ce 100644 --- a/appwrite/models/database_status_connections.py +++ b/appwrite/models/database_status_connections.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class DatabaseStatusConnections(AppwriteModel): current: float = Field(..., alias='current') max: float = Field(..., alias='max') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'current' not in data: + data['current'] = 0 + if 'max' not in data: + data['max'] = 100 + return data diff --git a/appwrite/models/database_status_replica.py b/appwrite/models/database_status_replica.py index cab729db..4f480433 100644 --- a/appwrite/models/database_status_replica.py +++ b/appwrite/models/database_status_replica.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,18 @@ class DatabaseStatusReplica(AppwriteModel): healthy: bool = Field(..., alias='healthy') replicating: Optional[bool] = Field(default=None, alias='replicating') lagseconds: Optional[float] = Field(default=None, alias='lagSeconds') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'index' not in data: + data['index'] = 0 + if 'role' not in data: + data['role'] = 'unknown' + if 'healthy' not in data: + data['healthy'] = False + return data diff --git a/appwrite/models/database_status_volume.py b/appwrite/models/database_status_volume.py index 654b089a..80a2286e 100644 --- a/appwrite/models/database_status_volume.py +++ b/appwrite/models/database_status_volume.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class DatabaseStatusVolume(AppwriteModel): usedpercent: str = Field(..., alias='usedPercent') available: str = Field(..., alias='available') mounted: bool = Field(..., alias='mounted') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'path' not in data: + data['path'] = '' + if 'usedPercent' not in data and 'usedpercent' not in data: + data['usedPercent'] = '0%' + if 'available' not in data: + data['available'] = '0GB' + if 'mounted' not in data: + data['mounted'] = False + return data diff --git a/appwrite/models/dedicated_database.py b/appwrite/models/dedicated_database.py index 5fbb15bc..69aea701 100644 --- a/appwrite/models/dedicated_database.py +++ b/appwrite/models/dedicated_database.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -20,9 +20,9 @@ class DedicatedDatabase(AppwriteModel): Project ID that owns this database. name : str Database display name. - api : str + api : Optional[str] Product API that owns this database: tablesdb, documentsdb, vectorsdb, mysql, postgresql, or mongodb. - engine : str + engine : Optional[str] Database engine: postgresql, mysql, or mongodb. Null until the backing reports one. version : str Database engine version. @@ -32,13 +32,13 @@ class DedicatedDatabase(AppwriteModel): Database backend provider. Possible values: edge. hostname : str Database hostname for connections. - connectionport : float + connectionport : Optional[float] Database port for connections. Derived from the engine when the backing has not reported one yet. connectionuser : str Database username for connections. connectionpassword : str Database password for connections. - credentialgeneration : float + credentialgeneration : Optional[float] Committed generation of the primary connection credentials. Null until the rotation contract has been initialized. connectionstring : str Full database connection string (URI format). @@ -47,7 +47,7 @@ class DedicatedDatabase(AppwriteModel): status : str Database status. Possible values: provisioning, ready, inactive, paused, failed, deleted, restoring, scaling. containerstatus : str - Container status for lifecycle-managed database runtimes: active or inactive. + Container status for lifecycle-managed database runtimes: active, inactive, or failed (a wake was declined because the backing namespace is gone). lastaccessedat : Optional[str] Last activity timestamp in ISO 8601 format. idleuntil : Optional[str] @@ -62,9 +62,9 @@ class DedicatedDatabase(AppwriteModel): Memory allocated in MB. storage : float Storage allocated in GB. - storagestatus : Optional[str] + storagestatus : str Storage resize status. Possible values: idle (no resize in flight), resizing (the volume is growing towards storageTargetGb). - storagetargetgb : Optional[float] + storagetargetgb : float Size in GB the volume is growing towards while storageStatus is resizing. 0 when no resize is in flight. storageresizestartedat : Optional[str] Time the in-flight storage resize started, in ISO 8601 format. @@ -95,7 +95,7 @@ class DedicatedDatabase(AppwriteModel): storageautoscalingthresholdpercent : float Storage usage percentage that triggers automatic expansion. storageautoscalingmaxgb : float - Maximum storage size in GB for autoscaling. 0 means no limit. + Maximum storage size in GB for autoscaling. Defaults to 3 times the specification's storage. 0 means no limit. maintenancewindowday : str Day of the week for the maintenance window. Possible values: sun, mon, tue, wed, thu, fri, sat. maintenancewindowhourutc : float @@ -121,16 +121,16 @@ class DedicatedDatabase(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') projectid: str = Field(..., alias='projectId') name: str = Field(..., alias='name') - api: str = Field(..., alias='api') - engine: str = Field(..., alias='engine') + api: Optional[str] = Field(default=None, alias='api') + engine: Optional[str] = Field(default=None, alias='engine') version: str = Field(..., alias='version') specification: str = Field(..., alias='specification') backend: str = Field(..., alias='backend') hostname: str = Field(..., alias='hostname') - connectionport: float = Field(..., alias='connectionPort') + connectionport: Optional[float] = Field(default=None, alias='connectionPort') connectionuser: str = Field(..., alias='connectionUser') connectionpassword: str = Field(..., alias='connectionPassword') - credentialgeneration: float = Field(..., alias='credentialGeneration') + credentialgeneration: Optional[float] = Field(default=None, alias='credentialGeneration') connectionstring: str = Field(..., alias='connectionString') ssl: bool = Field(..., alias='ssl') status: str = Field(..., alias='status') @@ -142,8 +142,8 @@ class DedicatedDatabase(AppwriteModel): cpu: float = Field(..., alias='cpu') memory: float = Field(..., alias='memory') storage: float = Field(..., alias='storage') - storagestatus: Optional[str] = Field(default=None, alias='storageStatus') - storagetargetgb: Optional[float] = Field(default=None, alias='storageTargetGb') + storagestatus: str = Field(..., alias='storageStatus') + storagetargetgb: float = Field(..., alias='storageTargetGb') storageresizestartedat: Optional[str] = Field(default=None, alias='storageResizeStartedAt') storageclass: str = Field(..., alias='storageClass') storagemaxgb: float = Field(..., alias='storageMaxGb') @@ -168,3 +168,102 @@ class DedicatedDatabase(AppwriteModel): sqlapimaxbytes: float = Field(..., alias='sqlApiMaxBytes') sqlapitimeoutseconds: float = Field(..., alias='sqlApiTimeoutSeconds') error: str = Field(..., alias='error') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'projectId' not in data and 'projectid' not in data: + data['projectId'] = '' + if 'name' not in data: + data['name'] = '' + if 'version' not in data: + data['version'] = '' + if 'specification' not in data: + data['specification'] = '' + if 'backend' not in data: + data['backend'] = '' + if 'hostname' not in data: + data['hostname'] = '' + if 'connectionUser' not in data and 'connectionuser' not in data: + data['connectionUser'] = '' + if 'connectionPassword' not in data and 'connectionpassword' not in data: + data['connectionPassword'] = '' + if 'connectionString' not in data and 'connectionstring' not in data: + data['connectionString'] = '' + if 'ssl' not in data: + data['ssl'] = False + if 'status' not in data: + data['status'] = 'provisioning' + if 'containerStatus' not in data and 'containerstatus' not in data: + data['containerStatus'] = '' + if 'lifecycleState' not in data and 'lifecyclestate' not in data: + data['lifecycleState'] = '' + if 'idleTimeoutMinutes' not in data and 'idletimeoutminutes' not in data: + data['idleTimeoutMinutes'] = 15 + if 'cpu' not in data: + data['cpu'] = 500 + if 'memory' not in data: + data['memory'] = 512 + if 'storage' not in data: + data['storage'] = 10 + if 'storageStatus' not in data and 'storagestatus' not in data: + data['storageStatus'] = 'idle' + if 'storageTargetGb' not in data and 'storagetargetgb' not in data: + data['storageTargetGb'] = 0 + if 'storageClass' not in data and 'storageclass' not in data: + data['storageClass'] = 'ssd' + if 'storageMaxGb' not in data and 'storagemaxgb' not in data: + data['storageMaxGb'] = 0 + if 'nodePool' not in data and 'nodepool' not in data: + data['nodePool'] = '' + if 'replicas' not in data: + data['replicas'] = 0 + if 'syncMode' not in data and 'syncmode' not in data: + data['syncMode'] = '' + if 'networkMaxConnections' not in data and 'networkmaxconnections' not in data: + data['networkMaxConnections'] = 100 + if 'networkIdleTimeoutSeconds' not in data and 'networkidletimeoutseconds' not in data: + data['networkIdleTimeoutSeconds'] = 900 + if 'networkIPAllowlist' not in data and 'networkipallowlist' not in data: + data['networkIPAllowlist'] = [] + if 'backupEnabled' not in data and 'backupenabled' not in data: + data['backupEnabled'] = True + if 'pitr' not in data: + data['pitr'] = True + if 'pitrRetentionDays' not in data and 'pitrretentiondays' not in data: + data['pitrRetentionDays'] = 7 + if 'storageAutoscaling' not in data and 'storageautoscaling' not in data: + data['storageAutoscaling'] = True + if 'storageAutoscalingThresholdPercent' not in data and 'storageautoscalingthresholdpercent' not in data: + data['storageAutoscalingThresholdPercent'] = 85 + if 'storageAutoscalingMaxGb' not in data and 'storageautoscalingmaxgb' not in data: + data['storageAutoscalingMaxGb'] = 0 + if 'maintenanceWindowDay' not in data and 'maintenancewindowday' not in data: + data['maintenanceWindowDay'] = 'sun' + if 'maintenanceWindowHourUtc' not in data and 'maintenancewindowhourutc' not in data: + data['maintenanceWindowHourUtc'] = 3 + if 'metricsEnabled' not in data and 'metricsenabled' not in data: + data['metricsEnabled'] = False + if 'sqlApiEnabled' not in data and 'sqlapienabled' not in data: + data['sqlApiEnabled'] = True + if 'sqlApiAllowedStatements' not in data and 'sqlapiallowedstatements' not in data: + data['sqlApiAllowedStatements'] = ['SELECT', 'INSERT', 'UPDATE', 'DELETE'] + if 'sqlApiMaxRows' not in data and 'sqlapimaxrows' not in data: + data['sqlApiMaxRows'] = 10000 + if 'sqlApiMaxBytes' not in data and 'sqlapimaxbytes' not in data: + data['sqlApiMaxBytes'] = 10485760 + if 'sqlApiTimeoutSeconds' not in data and 'sqlapitimeoutseconds' not in data: + data['sqlApiTimeoutSeconds'] = 30 + if 'error' not in data: + data['error'] = '' + return data diff --git a/appwrite/models/dedicated_database_backup.py b/appwrite/models/dedicated_database_backup.py index 40d47365..1c823b37 100644 --- a/appwrite/models/dedicated_database_backup.py +++ b/appwrite/models/dedicated_database_backup.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -63,3 +63,36 @@ class DedicatedDatabaseBackup(AppwriteModel): expiresat: Optional[str] = Field(default=None, alias='expiresAt') logposition: Optional[str] = Field(default=None, alias='logPosition') error: str = Field(..., alias='error') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if 'databaseId' not in data and 'databaseid' not in data: + data['databaseId'] = '' + if 'projectId' not in data and 'projectid' not in data: + data['projectId'] = '' + if 'policyId' not in data and 'policyid' not in data: + data['policyId'] = '' + if 'trigger' not in data: + data['trigger'] = 'manual' + if 'type' not in data: + data['type'] = 'full' + if 'requestedType' not in data and 'requestedtype' not in data: + data['requestedType'] = '' + if 'fallbackReason' not in data and 'fallbackreason' not in data: + data['fallbackReason'] = '' + if 'status' not in data: + data['status'] = 'pending' + if 'sizeBytes' not in data and 'sizebytes' not in data: + data['sizeBytes'] = 0 + if 'error' not in data: + data['error'] = '' + return data diff --git a/appwrite/models/dedicated_database_backup_list.py b/appwrite/models/dedicated_database_backup_list.py index d8d98696..9aa5b804 100644 --- a/appwrite/models/dedicated_database_backup_list.py +++ b/appwrite/models/dedicated_database_backup_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .dedicated_database_backup import DedicatedDatabaseBackup @@ -19,3 +19,16 @@ class DedicatedDatabaseBackupList(AppwriteModel): total: float = Field(..., alias='total') backups: List[DedicatedDatabaseBackup] = Field(..., alias='backups') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'backups' not in data: + data['backups'] = [] + return data diff --git a/appwrite/models/dedicated_database_backup_storage.py b/appwrite/models/dedicated_database_backup_storage.py index 039750c7..358720e4 100644 --- a/appwrite/models/dedicated_database_backup_storage.py +++ b/appwrite/models/dedicated_database_backup_storage.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,22 @@ class DedicatedDatabaseBackupStorage(AppwriteModel): region: str = Field(..., alias='region') prefix: str = Field(..., alias='prefix') endpoint: str = Field(..., alias='endpoint') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'provider' not in data: + data['provider'] = '' + if 'bucket' not in data: + data['bucket'] = '' + if 'region' not in data: + data['region'] = '' + if 'prefix' not in data: + data['prefix'] = 'backups/' + if 'endpoint' not in data: + data['endpoint'] = '' + return data diff --git a/appwrite/models/dedicated_database_branch.py b/appwrite/models/dedicated_database_branch.py index 4699ab6a..76b02b70 100644 --- a/appwrite/models/dedicated_database_branch.py +++ b/appwrite/models/dedicated_database_branch.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -20,7 +20,7 @@ class DedicatedDatabaseBranch(AppwriteModel): Unix timestamp when the branch expires. host : str Branch hostname for direct connections. - port : float + port : Optional[float] Branch port. Null until the backing reports one. database : str Advertised catalog the client connects to. MySQL/MariaDB use default; Postgres uses the routing label. @@ -41,10 +41,41 @@ class DedicatedDatabaseBranch(AppwriteModel): namespace: str = Field(..., alias='namespace') expiresat: float = Field(..., alias='expiresAt') host: str = Field(..., alias='host') - port: float = Field(..., alias='port') + port: Optional[float] = Field(default=None, alias='port') database: str = Field(..., alias='database') username: str = Field(..., alias='username') password: str = Field(..., alias='password') ssl: bool = Field(..., alias='ssl') engine: str = Field(..., alias='engine') connectionstring: str = Field(..., alias='connectionString') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'branchId' not in data and 'branchid' not in data: + data['branchId'] = '' + if 'branchName' not in data and 'branchname' not in data: + data['branchName'] = '' + if 'namespace' not in data: + data['namespace'] = '' + if 'expiresAt' not in data and 'expiresat' not in data: + data['expiresAt'] = 0 + if 'host' not in data: + data['host'] = '' + if 'database' not in data: + data['database'] = '' + if 'username' not in data: + data['username'] = '' + if 'password' not in data: + data['password'] = '' + if 'ssl' not in data: + data['ssl'] = False + if 'engine' not in data: + data['engine'] = '' + if 'connectionString' not in data and 'connectionstring' not in data: + data['connectionString'] = '' + return data diff --git a/appwrite/models/dedicated_database_branch_list.py b/appwrite/models/dedicated_database_branch_list.py index 9966ba57..cb283939 100644 --- a/appwrite/models/dedicated_database_branch_list.py +++ b/appwrite/models/dedicated_database_branch_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .dedicated_database_branch import DedicatedDatabaseBranch @@ -19,3 +19,16 @@ class DedicatedDatabaseBranchList(AppwriteModel): total: float = Field(..., alias='total') branches: List[DedicatedDatabaseBranch] = Field(..., alias='branches') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'branches' not in data: + data['branches'] = [] + return data diff --git a/appwrite/models/dedicated_database_execution.py b/appwrite/models/dedicated_database_execution.py index 4a9a5eda..02fab8ed 100644 --- a/appwrite/models/dedicated_database_execution.py +++ b/appwrite/models/dedicated_database_execution.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .dedicated_database_execution_column import DedicatedDatabaseExecutionColumn @@ -31,3 +31,24 @@ class DedicatedDatabaseExecution(AppwriteModel): durationms: float = Field(..., alias='durationMs') truncated: bool = Field(..., alias='truncated') bytes: float = Field(..., alias='bytes') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'rows' not in data: + data['rows'] = [] + if 'rowCount' not in data and 'rowcount' not in data: + data['rowCount'] = 0 + if 'columns' not in data: + data['columns'] = [] + if 'durationMs' not in data and 'durationms' not in data: + data['durationMs'] = 0 + if 'truncated' not in data: + data['truncated'] = False + if 'bytes' not in data: + data['bytes'] = 0 + return data diff --git a/appwrite/models/dedicated_database_execution_column.py b/appwrite/models/dedicated_database_execution_column.py index 095e7e59..a0adce80 100644 --- a/appwrite/models/dedicated_database_execution_column.py +++ b/appwrite/models/dedicated_database_execution_column.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class DedicatedDatabaseExecutionColumn(AppwriteModel): name: str = Field(..., alias='name') type: str = Field(..., alias='type') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'name' not in data: + data['name'] = '' + if 'type' not in data: + data['type'] = '' + return data diff --git a/appwrite/models/dedicated_database_extensions.py b/appwrite/models/dedicated_database_extensions.py index 363e6374..d138bbed 100644 --- a/appwrite/models/dedicated_database_extensions.py +++ b/appwrite/models/dedicated_database_extensions.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .postgres_extension import PostgresExtension @@ -22,3 +22,18 @@ class DedicatedDatabaseExtensions(AppwriteModel): installed: List[Any] = Field(..., alias='installed') available: List[Any] = Field(..., alias='available') metadata: List[PostgresExtension] = Field(..., alias='metadata') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'installed' not in data: + data['installed'] = [] + if 'available' not in data: + data['available'] = [] + if 'metadata' not in data: + data['metadata'] = [] + return data diff --git a/appwrite/models/dedicated_database_list.py b/appwrite/models/dedicated_database_list.py index f7e50415..dd32ba25 100644 --- a/appwrite/models/dedicated_database_list.py +++ b/appwrite/models/dedicated_database_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .dedicated_database import DedicatedDatabase @@ -19,3 +19,16 @@ class DedicatedDatabaseList(AppwriteModel): total: float = Field(..., alias='total') databases: List[DedicatedDatabase] = Field(..., alias='databases') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'databases' not in data: + data['databases'] = [] + return data diff --git a/appwrite/models/dedicated_database_member.py b/appwrite/models/dedicated_database_member.py index 55426f3f..91a8aaad 100644 --- a/appwrite/models/dedicated_database_member.py +++ b/appwrite/models/dedicated_database_member.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,18 @@ class DedicatedDatabaseMember(AppwriteModel): status: str = Field(..., alias='status') replicating: Optional[bool] = Field(default=None, alias='replicating') lagseconds: Optional[float] = Field(default=None, alias='lagSeconds') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'role' not in data: + data['role'] = 'unknown' + if 'status' not in data: + data['status'] = '' + return data diff --git a/appwrite/models/dedicated_database_operation.py b/appwrite/models/dedicated_database_operation.py index d9814c58..af80395d 100644 --- a/appwrite/models/dedicated_database_operation.py +++ b/appwrite/models/dedicated_database_operation.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -45,3 +45,28 @@ class DedicatedDatabaseOperation(AppwriteModel): completedat: Optional[str] = Field(default=None, alias='completedAt') errorcode: str = Field(..., alias='errorCode') errormessage: str = Field(..., alias='errorMessage') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if 'databaseId' not in data and 'databaseid' not in data: + data['databaseId'] = '' + if 'type' not in data: + data['type'] = '' + if 'status' not in data: + data['status'] = '' + if 'attempts' not in data: + data['attempts'] = 0 + if 'errorCode' not in data and 'errorcode' not in data: + data['errorCode'] = '' + if 'errorMessage' not in data and 'errormessage' not in data: + data['errorMessage'] = '' + return data diff --git a/appwrite/models/dedicated_database_operation_list.py b/appwrite/models/dedicated_database_operation_list.py index 30d2cc8c..727c4f49 100644 --- a/appwrite/models/dedicated_database_operation_list.py +++ b/appwrite/models/dedicated_database_operation_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .dedicated_database_operation import DedicatedDatabaseOperation @@ -19,3 +19,16 @@ class DedicatedDatabaseOperationList(AppwriteModel): total: float = Field(..., alias='total') operations: List[DedicatedDatabaseOperation] = Field(..., alias='operations') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'operations' not in data: + data['operations'] = [] + return data diff --git a/appwrite/models/dedicated_database_pitr_windows.py b/appwrite/models/dedicated_database_pitr_windows.py index 243710e6..4d35ccf5 100644 --- a/appwrite/models/dedicated_database_pitr_windows.py +++ b/appwrite/models/dedicated_database_pitr_windows.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class DedicatedDatabasePITRWindows(AppwriteModel): earliest: str = Field(..., alias='earliest') latest: str = Field(..., alias='latest') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'earliest' not in data: + data['earliest'] = '' + if 'latest' not in data: + data['latest'] = '' + return data diff --git a/appwrite/models/dedicated_database_pooler.py b/appwrite/models/dedicated_database_pooler.py index 3316d96f..3c6b221b 100644 --- a/appwrite/models/dedicated_database_pooler.py +++ b/appwrite/models/dedicated_database_pooler.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -42,3 +42,32 @@ class DedicatedDatabasePooler(AppwriteModel): poolercpulimit: str = Field(..., alias='poolerCpuLimit') poolermemoryrequest: str = Field(..., alias='poolerMemoryRequest') poolermemorylimit: str = Field(..., alias='poolerMemoryLimit') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'enabled' not in data: + data['enabled'] = False + if 'mode' not in data: + data['mode'] = 'transaction' + if 'maxConnections' not in data and 'maxconnections' not in data: + data['maxConnections'] = 100 + if 'defaultPoolSize' not in data and 'defaultpoolsize' not in data: + data['defaultPoolSize'] = 20 + if 'port' not in data: + data['port'] = 6432 + if 'readWriteSplitting' not in data and 'readwritesplitting' not in data: + data['readWriteSplitting'] = False + if 'poolerCpuRequest' not in data and 'poolercpurequest' not in data: + data['poolerCpuRequest'] = '' + if 'poolerCpuLimit' not in data and 'poolercpulimit' not in data: + data['poolerCpuLimit'] = '' + if 'poolerMemoryRequest' not in data and 'poolermemoryrequest' not in data: + data['poolerMemoryRequest'] = '' + if 'poolerMemoryLimit' not in data and 'poolermemorylimit' not in data: + data['poolerMemoryLimit'] = '' + return data diff --git a/appwrite/models/dedicated_database_replicas.py b/appwrite/models/dedicated_database_replicas.py index fc035b2b..9d764043 100644 --- a/appwrite/models/dedicated_database_replicas.py +++ b/appwrite/models/dedicated_database_replicas.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .dedicated_database_member import DedicatedDatabaseMember @@ -37,3 +37,24 @@ class DedicatedDatabaseReplicas(AppwriteModel): syncstandbycount: float = Field(..., alias='syncStandbyCount') syncstateconfirmed: Optional[bool] = Field(default=None, alias='syncStateConfirmed') members: List[DedicatedDatabaseMember] = Field(..., alias='members') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'replicas' not in data: + data['replicas'] = 0 + if 'syncMode' not in data and 'syncmode' not in data: + data['syncMode'] = 'async' + if 'syncDegraded' not in data and 'syncdegraded' not in data: + data['syncDegraded'] = False + if 'syncAcknowledgements' not in data and 'syncacknowledgements' not in data: + data['syncAcknowledgements'] = 0 + if 'syncStandbyCount' not in data and 'syncstandbycount' not in data: + data['syncStandbyCount'] = 0 + if 'members' not in data: + data['members'] = [] + return data diff --git a/appwrite/models/dedicated_database_restoration.py b/appwrite/models/dedicated_database_restoration.py index 7965c50d..f44b35e8 100644 --- a/appwrite/models/dedicated_database_restoration.py +++ b/appwrite/models/dedicated_database_restoration.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -16,21 +16,23 @@ class DedicatedDatabaseRestoration(AppwriteModel): Restoration creation time in ISO 8601 format. databaseid : str Database ID being restored into. - sourcedatabaseid : str + sourcedatabaseid : Optional[str] Source database ID when restoring a backup into another database. projectid : str Project ID. - backupid : str + backupid : Optional[str] Backup ID used for restoration (null for PITR). type : str Restoration type. Possible values: backup (restore from a specific backup snapshot), pitr (point-in-time recovery to a specific timestamp). + restoremode : str + Where the backup was restored. Possible values: in_place (replayed over the database that took the backup), clone (recovered onto a second workload beside the database, which keeps serving until the clone is promoted onto its endpoint), copy (recovered onto a separate database with its own endpoint). status : str Restoration status. Possible values: pending (queued for processing), running (currently in progress), completed (successfully finished), failed (encountered an error). - targettime : str + targettime : Optional[str] Target time for PITR restoration in ISO 8601 format. - startedat : str + startedat : Optional[str] Restoration start time in ISO 8601 format. - completedat : str + completedat : Optional[str] Restoration completion time in ISO 8601 format. error : str Error message if restoration failed. @@ -39,12 +41,38 @@ class DedicatedDatabaseRestoration(AppwriteModel): id: str = Field(..., alias='$id') createdat: str = Field(..., alias='$createdAt') databaseid: str = Field(..., alias='databaseId') - sourcedatabaseid: str = Field(..., alias='sourceDatabaseId') + sourcedatabaseid: Optional[str] = Field(default=None, alias='sourceDatabaseId') projectid: str = Field(..., alias='projectId') - backupid: str = Field(..., alias='backupId') + backupid: Optional[str] = Field(default=None, alias='backupId') type: str = Field(..., alias='type') + restoremode: str = Field(..., alias='restoreMode') status: str = Field(..., alias='status') - targettime: str = Field(..., alias='targetTime') - startedat: str = Field(..., alias='startedAt') - completedat: str = Field(..., alias='completedAt') + targettime: Optional[str] = Field(default=None, alias='targetTime') + startedat: Optional[str] = Field(default=None, alias='startedAt') + completedat: Optional[str] = Field(default=None, alias='completedAt') error: str = Field(..., alias='error') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if 'databaseId' not in data and 'databaseid' not in data: + data['databaseId'] = '' + if 'projectId' not in data and 'projectid' not in data: + data['projectId'] = '' + if 'type' not in data: + data['type'] = 'backup' + if 'restoreMode' not in data and 'restoremode' not in data: + data['restoreMode'] = 'in_place' + if 'status' not in data: + data['status'] = 'pending' + if 'error' not in data: + data['error'] = '' + return data diff --git a/appwrite/models/dedicated_database_restoration_list.py b/appwrite/models/dedicated_database_restoration_list.py index 8eac8c70..8d2a092b 100644 --- a/appwrite/models/dedicated_database_restoration_list.py +++ b/appwrite/models/dedicated_database_restoration_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .dedicated_database_restoration import DedicatedDatabaseRestoration @@ -19,3 +19,16 @@ class DedicatedDatabaseRestorationList(AppwriteModel): total: float = Field(..., alias='total') restorations: List[DedicatedDatabaseRestoration] = Field(..., alias='restorations') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'restorations' not in data: + data['restorations'] = [] + return data diff --git a/appwrite/models/dedicated_database_specification.py b/appwrite/models/dedicated_database_specification.py index 35922431..1bc7af29 100644 --- a/appwrite/models/dedicated_database_specification.py +++ b/appwrite/models/dedicated_database_specification.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -16,13 +16,13 @@ class DedicatedDatabaseSpecification(AppwriteModel): Human readable specification name. price : float Monthly price of the specification in USD. - storageoveragerate : Optional[float] + storageoveragerate : float Price per GB of storage above the included amount, per month, in USD. - bandwidthoveragerate : Optional[float] + bandwidthoveragerate : float Price per GB of bandwidth above the included amount, per month, in USD. - replicarate : Optional[float] + replicarate : float High availability replica price as a fraction of the specification price. - pitrrate : Optional[float] + pitrrate : float Point-in-time recovery price as a fraction of the specification price. cpu : float Allocated CPU in millicores. @@ -41,13 +41,48 @@ class DedicatedDatabaseSpecification(AppwriteModel): slug: str = Field(..., alias='slug') name: str = Field(..., alias='name') price: float = Field(..., alias='price') - storageoveragerate: Optional[float] = Field(default=None, alias='storageOverageRate') - bandwidthoveragerate: Optional[float] = Field(default=None, alias='bandwidthOverageRate') - replicarate: Optional[float] = Field(default=None, alias='replicaRate') - pitrrate: Optional[float] = Field(default=None, alias='pitrRate') + storageoveragerate: float = Field(..., alias='storageOverageRate') + bandwidthoveragerate: float = Field(..., alias='bandwidthOverageRate') + replicarate: float = Field(..., alias='replicaRate') + pitrrate: float = Field(..., alias='pitrRate') cpu: float = Field(..., alias='cpu') memory: float = Field(..., alias='memory') maxconnections: float = Field(..., alias='maxConnections') includedstorage: float = Field(..., alias='includedStorage') includedbandwidth: float = Field(..., alias='includedBandwidth') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'slug' not in data: + data['slug'] = '' + if 'name' not in data: + data['name'] = '' + if 'price' not in data: + data['price'] = 0 + if 'storageOverageRate' not in data and 'storageoveragerate' not in data: + data['storageOverageRate'] = 0 + if 'bandwidthOverageRate' not in data and 'bandwidthoveragerate' not in data: + data['bandwidthOverageRate'] = 0 + if 'replicaRate' not in data and 'replicarate' not in data: + data['replicaRate'] = 0 + if 'pitrRate' not in data and 'pitrrate' not in data: + data['pitrRate'] = 0 + if 'cpu' not in data: + data['cpu'] = 0 + if 'memory' not in data: + data['memory'] = 0 + if 'maxConnections' not in data and 'maxconnections' not in data: + data['maxConnections'] = 0 + if 'includedStorage' not in data and 'includedstorage' not in data: + data['includedStorage'] = 0 + if 'includedBandwidth' not in data and 'includedbandwidth' not in data: + data['includedBandwidth'] = 0 + if 'enabled' not in data: + data['enabled'] = False + return data diff --git a/appwrite/models/dedicated_database_specification_list.py b/appwrite/models/dedicated_database_specification_list.py index 92c0b23f..f3ff1209 100644 --- a/appwrite/models/dedicated_database_specification_list.py +++ b/appwrite/models/dedicated_database_specification_list.py @@ -1,9 +1,8 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .dedicated_database_specification import DedicatedDatabaseSpecification -from .dedicated_database_specification_pricing import DedicatedDatabaseSpecificationPricing class DedicatedDatabaseSpecificationList(AppwriteModel): @@ -16,10 +15,20 @@ class DedicatedDatabaseSpecificationList(AppwriteModel): List of dedicated database specifications. total : float Total number of specifications. - pricing : DedicatedDatabaseSpecificationPricing - Overage and add-on pricing shared across all specifications. """ specifications: List[DedicatedDatabaseSpecification] = Field(..., alias='specifications') total: float = Field(..., alias='total') - pricing: DedicatedDatabaseSpecificationPricing = Field(..., alias='pricing') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'specifications' not in data: + data['specifications'] = [] + if 'total' not in data: + data['total'] = 0 + return data diff --git a/appwrite/models/dedicated_database_specification_pricing.py b/appwrite/models/dedicated_database_specification_pricing.py deleted file mode 100644 index 83b03a6a..00000000 --- a/appwrite/models/dedicated_database_specification_pricing.py +++ /dev/null @@ -1,26 +0,0 @@ -from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr - -from .base_model import AppwriteModel - - -class DedicatedDatabaseSpecificationPricing(AppwriteModel): - """ - SpecificationPricing - - Attributes - ---------- - storageoveragerate : float - Price per GB of storage above the included amount, per month, in USD. - bandwidthoveragerate : float - Price per GB of bandwidth above the included amount, per month, in USD. - replicarate : float - High availability replica price as a fraction of the specification cost. - pitrrate : float - Point-in-time recovery price as a fraction of the specification cost. - """ - - storageoveragerate: float = Field(..., alias='storageOverageRate') - bandwidthoveragerate: float = Field(..., alias='bandwidthOverageRate') - replicarate: float = Field(..., alias='replicaRate') - pitrrate: float = Field(..., alias='pitrRate') diff --git a/appwrite/models/deployment.py b/appwrite/models/deployment.py index f4baf0c9..56e36cb4 100644 --- a/appwrite/models/deployment.py +++ b/appwrite/models/deployment.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.deployment_status import DeploymentStatus @@ -94,3 +94,64 @@ class Deployment(AppwriteModel): providercommiturl: str = Field(..., alias='providerCommitUrl') providerbranch: str = Field(..., alias='providerBranch') providerbranchurl: str = Field(..., alias='providerBranchUrl') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'type' not in data: + data['type'] = '' + if 'resourceId' not in data and 'resourceid' not in data: + data['resourceId'] = '' + if 'resourceType' not in data and 'resourcetype' not in data: + data['resourceType'] = '' + if 'entrypoint' not in data: + data['entrypoint'] = '' + if 'sourceSize' not in data and 'sourcesize' not in data: + data['sourceSize'] = 0 + if 'buildSize' not in data and 'buildsize' not in data: + data['buildSize'] = 0 + if 'totalSize' not in data and 'totalsize' not in data: + data['totalSize'] = 0 + if 'buildId' not in data and 'buildid' not in data: + data['buildId'] = '' + if 'activate' not in data: + data['activate'] = False + if 'screenshotLight' not in data and 'screenshotlight' not in data: + data['screenshotLight'] = '' + if 'screenshotDark' not in data and 'screenshotdark' not in data: + data['screenshotDark'] = '' + if 'buildLogs' not in data and 'buildlogs' not in data: + data['buildLogs'] = '' + if 'buildDuration' not in data and 'buildduration' not in data: + data['buildDuration'] = 0 + if 'providerRepositoryName' not in data and 'providerrepositoryname' not in data: + data['providerRepositoryName'] = '' + if 'providerRepositoryOwner' not in data and 'providerrepositoryowner' not in data: + data['providerRepositoryOwner'] = '' + if 'providerRepositoryUrl' not in data and 'providerrepositoryurl' not in data: + data['providerRepositoryUrl'] = '' + if 'providerCommitHash' not in data and 'providercommithash' not in data: + data['providerCommitHash'] = '' + if 'providerCommitAuthorUrl' not in data and 'providercommitauthorurl' not in data: + data['providerCommitAuthorUrl'] = '' + if 'providerCommitAuthor' not in data and 'providercommitauthor' not in data: + data['providerCommitAuthor'] = '' + if 'providerCommitMessage' not in data and 'providercommitmessage' not in data: + data['providerCommitMessage'] = '' + if 'providerCommitUrl' not in data and 'providercommiturl' not in data: + data['providerCommitUrl'] = '' + if 'providerBranch' not in data and 'providerbranch' not in data: + data['providerBranch'] = '' + if 'providerBranchUrl' not in data and 'providerbranchurl' not in data: + data['providerBranchUrl'] = '' + return data diff --git a/appwrite/models/deployment_list.py b/appwrite/models/deployment_list.py index d3c435d9..9eba292c 100644 --- a/appwrite/models/deployment_list.py +++ b/appwrite/models/deployment_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .deployment import Deployment @@ -19,3 +19,16 @@ class DeploymentList(AppwriteModel): total: float = Field(..., alias='total') deployments: List[Deployment] = Field(..., alias='deployments') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'deployments' not in data: + data['deployments'] = [] + return data diff --git a/appwrite/models/dev_key.py b/appwrite/models/dev_key.py deleted file mode 100644 index c36cf0f6..00000000 --- a/appwrite/models/dev_key.py +++ /dev/null @@ -1,38 +0,0 @@ -from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr - -from .base_model import AppwriteModel - - -class DevKey(AppwriteModel): - """ - DevKey - - Attributes - ---------- - id : str - Key ID. - createdat : str - Key creation date in ISO 8601 format. - updatedat : str - Key update date in ISO 8601 format. - name : str - Key name. - expire : str - Key expiration date in ISO 8601 format. - secret : str - Secret key. - accessedat : str - Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours. - sdks : List[Any] - List of SDK user agents that used this key. - """ - - id: str = Field(..., alias='$id') - createdat: str = Field(..., alias='$createdAt') - updatedat: str = Field(..., alias='$updatedAt') - name: str = Field(..., alias='name') - expire: str = Field(..., alias='expire') - secret: str = Field(..., alias='secret') - accessedat: str = Field(..., alias='accessedAt') - sdks: List[Any] = Field(..., alias='sdks') diff --git a/appwrite/models/dns_record.py b/appwrite/models/dns_record.py index 9911c905..612c896b 100644 --- a/appwrite/models/dns_record.py +++ b/appwrite/models/dns_record.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -48,3 +48,36 @@ class DnsRecord(AppwriteModel): weight: float = Field(..., alias='weight') port: float = Field(..., alias='port') comment: str = Field(..., alias='comment') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'type' not in data: + data['type'] = '' + if 'name' not in data: + data['name'] = '' + if 'value' not in data: + data['value'] = '' + if 'ttl' not in data: + data['ttl'] = 3600 + if 'priority' not in data: + data['priority'] = 0 + if 'lock' not in data: + data['lock'] = False + if 'weight' not in data: + data['weight'] = 0 + if 'port' not in data: + data['port'] = 0 + if 'comment' not in data: + data['comment'] = '' + return data diff --git a/appwrite/models/dns_records_list.py b/appwrite/models/dns_records_list.py index a3948c08..50e4f097 100644 --- a/appwrite/models/dns_records_list.py +++ b/appwrite/models/dns_records_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .dns_record import DnsRecord @@ -19,3 +19,16 @@ class DnsRecordsList(AppwriteModel): total: float = Field(..., alias='total') dnsrecords: List[DnsRecord] = Field(..., alias='dnsRecords') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'dnsRecords' not in data and 'dnsrecords' not in data: + data['dnsRecords'] = [] + return data diff --git a/appwrite/models/document.py b/appwrite/models/document.py index f59435f1..b52a4e4f 100644 --- a/appwrite/models/document.py +++ b/appwrite/models/document.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast, Generic, TypeVar, Type -from pydantic import Field, PrivateAttr, TypeAdapter, model_serializer +from pydantic import Field, PrivateAttr, TypeAdapter, model_validator, model_serializer from .base_model import AppwriteModel @@ -38,6 +38,29 @@ class Document(AppwriteModel, Generic[T]): updatedat: str = Field(..., alias='$updatedAt') permissions: List[Any] = Field(..., alias='$permissions') + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$sequence' not in data and 'sequence' not in data: + data['$sequence'] = '' + if '$collectionId' not in data and 'collectionid' not in data: + data['$collectionId'] = '' + if '$databaseId' not in data and 'databaseid' not in data: + data['$databaseId'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if '$permissions' not in data and 'permissions' not in data: + data['$permissions'] = [] + return data + @classmethod def with_data(cls, data: Dict[str, Any], model_type: Type[T] = dict) -> 'Document[T]': """Create Document instance with typed data.""" diff --git a/appwrite/models/document_list.py b/appwrite/models/document_list.py index ff2045dc..732e9f5f 100644 --- a/appwrite/models/document_list.py +++ b/appwrite/models/document_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast, Generic, TypeVar, Type -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .document import Document @@ -22,6 +22,19 @@ class DocumentList(AppwriteModel, Generic[T]): total: float = Field(..., alias='total') documents: List[Document[T]] = Field(..., alias='documents') + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'documents' not in data: + data['documents'] = [] + return data + @classmethod def with_data(cls, data: Dict[str, Any], model_type: Type[T] = dict) -> 'DocumentList[T]': """Create DocumentList instance with typed data.""" diff --git a/appwrite/models/domain.py b/appwrite/models/domain.py index 26e3ee52..f68dad9e 100644 --- a/appwrite/models/domain.py +++ b/appwrite/models/domain.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.domain_transfer_status_enum import DomainTransferStatusEnum @@ -53,3 +53,36 @@ class Domain(AppwriteModel): transferstatus: Optional[DomainTransferStatusEnum] = Field(default=None, alias='transferStatus') teamid: str = Field(..., alias='teamId') dnsrecords: List[DnsRecord] = Field(..., alias='dnsRecords') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'domain' not in data: + data['domain'] = '' + if 'registrar' not in data: + data['registrar'] = '' + if 'nameservers' not in data: + data['nameservers'] = '' + if 'expire' not in data: + data['expire'] = '' + if 'renewal' not in data: + data['renewal'] = '' + if 'autoRenewal' not in data and 'autorenewal' not in data: + data['autoRenewal'] = False + if 'renewalPrice' not in data and 'renewalprice' not in data: + data['renewalPrice'] = 0 + if 'teamId' not in data and 'teamid' not in data: + data['teamId'] = '' + if 'dnsRecords' not in data and 'dnsrecords' not in data: + data['dnsRecords'] = [] + return data diff --git a/appwrite/models/domain_price.py b/appwrite/models/domain_price.py index 298d583c..6ab77ae3 100644 --- a/appwrite/models/domain_price.py +++ b/appwrite/models/domain_price.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -36,3 +36,24 @@ class DomainPrice(AppwriteModel): premium: bool = Field(..., alias='premium') renewalprice: Optional[float] = Field(default=None, alias='renewalPrice') renewalperiodyears: float = Field(..., alias='renewalPeriodYears') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'domain' not in data: + data['domain'] = '' + if 'tld' not in data: + data['tld'] = '' + if 'available' not in data: + data['available'] = False + if 'periodYears' not in data and 'periodyears' not in data: + data['periodYears'] = 1 + if 'premium' not in data: + data['premium'] = False + if 'renewalPeriodYears' not in data and 'renewalperiodyears' not in data: + data['renewalPeriodYears'] = 1 + return data diff --git a/appwrite/models/domain_prices_list.py b/appwrite/models/domain_prices_list.py index 773538f4..b2b16412 100644 --- a/appwrite/models/domain_prices_list.py +++ b/appwrite/models/domain_prices_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .domain_price import DomainPrice @@ -19,3 +19,16 @@ class DomainPricesList(AppwriteModel): total: float = Field(..., alias='total') prices: List[DomainPrice] = Field(..., alias='prices') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'prices' not in data: + data['prices'] = [] + return data diff --git a/appwrite/models/domain_transfer_status.py b/appwrite/models/domain_transfer_status.py index 3a9e9d4c..c7a6df77 100644 --- a/appwrite/models/domain_transfer_status.py +++ b/appwrite/models/domain_transfer_status.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.domain_transfer_status_enum import DomainTransferStatusEnum @@ -22,3 +22,18 @@ class DomainTransferStatus(AppwriteModel): status: DomainTransferStatusEnum = Field(..., alias='status') reason: str = Field(..., alias='reason') timestamp: str = Field(..., alias='timestamp') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'status' not in data: + data['status'] = 'pending_registry' + if 'reason' not in data: + data['reason'] = '' + if 'timestamp' not in data: + data['timestamp'] = '' + return data diff --git a/appwrite/models/domains_list.py b/appwrite/models/domains_list.py index 6bde8fba..80af58d8 100644 --- a/appwrite/models/domains_list.py +++ b/appwrite/models/domains_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .domain import Domain @@ -19,3 +19,16 @@ class DomainsList(AppwriteModel): total: float = Field(..., alias='total') domains: List[Domain] = Field(..., alias='domains') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'domains' not in data: + data['domains'] = [] + return data diff --git a/appwrite/models/email_template.py b/appwrite/models/email_template.py index 302173e9..ebb62bfd 100644 --- a/appwrite/models/email_template.py +++ b/appwrite/models/email_template.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -36,3 +36,28 @@ class EmailTemplate(AppwriteModel): replytoemail: str = Field(..., alias='replyToEmail') replytoname: str = Field(..., alias='replyToName') subject: str = Field(..., alias='subject') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'templateId' not in data and 'templateid' not in data: + data['templateId'] = '' + if 'locale' not in data: + data['locale'] = '' + if 'message' not in data: + data['message'] = '' + if 'senderName' not in data and 'sendername' not in data: + data['senderName'] = '' + if 'senderEmail' not in data and 'senderemail' not in data: + data['senderEmail'] = '' + if 'replyToEmail' not in data and 'replytoemail' not in data: + data['replyToEmail'] = '' + if 'replyToName' not in data and 'replytoname' not in data: + data['replyToName'] = '' + if 'subject' not in data: + data['subject'] = '' + return data diff --git a/appwrite/models/email_template_list.py b/appwrite/models/email_template_list.py index 3a601e4a..e774362a 100644 --- a/appwrite/models/email_template_list.py +++ b/appwrite/models/email_template_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .email_template import EmailTemplate @@ -19,3 +19,16 @@ class EmailTemplateList(AppwriteModel): total: float = Field(..., alias='total') templates: List[EmailTemplate] = Field(..., alias='templates') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'templates' not in data: + data['templates'] = [] + return data diff --git a/appwrite/models/embedding.py b/appwrite/models/embedding.py index c308479a..e6ccbe94 100644 --- a/appwrite/models/embedding.py +++ b/appwrite/models/embedding.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class Embedding(AppwriteModel): dimension: float = Field(..., alias='dimension') embedding: List[Any] = Field(..., alias='embedding') error: str = Field(..., alias='error') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'model' not in data: + data['model'] = '' + if 'dimension' not in data: + data['dimension'] = 0 + if 'embedding' not in data: + data['embedding'] = [] + if 'error' not in data: + data['error'] = '' + return data diff --git a/appwrite/models/embedding_list.py b/appwrite/models/embedding_list.py index afa3a12e..ed680b53 100644 --- a/appwrite/models/embedding_list.py +++ b/appwrite/models/embedding_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .embedding import Embedding @@ -19,3 +19,16 @@ class EmbeddingList(AppwriteModel): total: float = Field(..., alias='total') embeddings: List[Embedding] = Field(..., alias='embeddings') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'embeddings' not in data: + data['embeddings'] = [] + return data diff --git a/appwrite/models/ephemeral_key.py b/appwrite/models/ephemeral_key.py index ed21e512..7800c687 100644 --- a/appwrite/models/ephemeral_key.py +++ b/appwrite/models/ephemeral_key.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -39,3 +39,30 @@ class EphemeralKey(AppwriteModel): secret: str = Field(..., alias='secret') accessedat: str = Field(..., alias='accessedAt') sdks: List[Any] = Field(..., alias='sdks') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'expire' not in data: + data['expire'] = '' + if 'scopes' not in data: + data['scopes'] = [] + if 'secret' not in data: + data['secret'] = '' + if 'accessedAt' not in data and 'accessedat' not in data: + data['accessedAt'] = '' + if 'sdks' not in data: + data['sdks'] = [] + return data diff --git a/appwrite/models/execution.py b/appwrite/models/execution.py index 37706152..51a84e4f 100644 --- a/appwrite/models/execution.py +++ b/appwrite/models/execution.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.execution_resource_type import ExecutionResourceType @@ -29,7 +29,7 @@ class Execution(AppwriteModel): deploymentid : str Deployment ID used to create the execution. trigger : ExecutionTrigger - The trigger that caused the resource to execute. Possible values can be: `http`, `schedule`, or `event`. + The trigger that caused the resource to execute. Possible values can be: `http`, `schedule`, `event`, or `email`. status : ExecutionStatus The status of the resource execution. Possible values can be: `waiting`, `processing`, `completed`, `failed`, or `scheduled`. requestmethod : str @@ -49,7 +49,7 @@ class Execution(AppwriteModel): errors : str Resource errors. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload. duration : float - Resource(function/site) execution duration in seconds. + Total time the resource(function/site) took to respond, in seconds. scheduledat : Optional[str] The scheduled time for execution. If left empty, execution will be queued immediately. """ @@ -73,3 +73,44 @@ class Execution(AppwriteModel): errors: str = Field(..., alias='errors') duration: float = Field(..., alias='duration') scheduledat: Optional[str] = Field(default=None, alias='scheduledAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if '$permissions' not in data and 'permissions' not in data: + data['$permissions'] = [] + if 'resourceId' not in data and 'resourceid' not in data: + data['resourceId'] = '' + if 'resourceType' not in data and 'resourcetype' not in data: + data['resourceType'] = 'functions' + if 'deploymentId' not in data and 'deploymentid' not in data: + data['deploymentId'] = '' + if 'requestMethod' not in data and 'requestmethod' not in data: + data['requestMethod'] = '' + if 'requestPath' not in data and 'requestpath' not in data: + data['requestPath'] = '' + if 'requestHeaders' not in data and 'requestheaders' not in data: + data['requestHeaders'] = [] + if 'responseStatusCode' not in data and 'responsestatuscode' not in data: + data['responseStatusCode'] = 0 + if 'responseBody' not in data and 'responsebody' not in data: + data['responseBody'] = '' + if 'responseHeaders' not in data and 'responseheaders' not in data: + data['responseHeaders'] = [] + if 'logs' not in data: + data['logs'] = '' + if 'errors' not in data: + data['errors'] = '' + if 'duration' not in data: + data['duration'] = 0 + return data diff --git a/appwrite/models/execution_list.py b/appwrite/models/execution_list.py index a3adbe24..8224edae 100644 --- a/appwrite/models/execution_list.py +++ b/appwrite/models/execution_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .execution import Execution @@ -19,3 +19,16 @@ class ExecutionList(AppwriteModel): total: float = Field(..., alias='total') executions: List[Execution] = Field(..., alias='executions') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'executions' not in data: + data['executions'] = [] + return data diff --git a/appwrite/models/file.py b/appwrite/models/file.py index dbf040c8..997d6cef 100644 --- a/appwrite/models/file.py +++ b/appwrite/models/file.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -60,3 +60,44 @@ class File(AppwriteModel): chunksuploaded: float = Field(..., alias='chunksUploaded') encryption: bool = Field(..., alias='encryption') compression: str = Field(..., alias='compression') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'bucketId' not in data and 'bucketid' not in data: + data['bucketId'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if '$permissions' not in data and 'permissions' not in data: + data['$permissions'] = [] + if 'name' not in data: + data['name'] = '' + if 'folder' not in data: + data['folder'] = '' + if 'key' not in data: + data['key'] = '' + if 'signature' not in data: + data['signature'] = '' + if 'mimeType' not in data and 'mimetype' not in data: + data['mimeType'] = '' + if 'sizeOriginal' not in data and 'sizeoriginal' not in data: + data['sizeOriginal'] = 0 + if 'sizeActual' not in data and 'sizeactual' not in data: + data['sizeActual'] = 0 + if 'chunksTotal' not in data and 'chunkstotal' not in data: + data['chunksTotal'] = 0 + if 'chunksUploaded' not in data and 'chunksuploaded' not in data: + data['chunksUploaded'] = 0 + if 'encryption' not in data: + data['encryption'] = False + if 'compression' not in data: + data['compression'] = 'none' + return data diff --git a/appwrite/models/file_list.py b/appwrite/models/file_list.py index c5166525..ff46006f 100644 --- a/appwrite/models/file_list.py +++ b/appwrite/models/file_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .file import File @@ -19,3 +19,16 @@ class FileList(AppwriteModel): total: float = Field(..., alias='total') files: List[File] = Field(..., alias='files') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'files' not in data: + data['files'] = [] + return data diff --git a/appwrite/models/framework.py b/appwrite/models/framework.py index f9fc73d2..1180f7b2 100644 --- a/appwrite/models/framework.py +++ b/appwrite/models/framework.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .framework_adapter import FrameworkAdapter @@ -28,3 +28,22 @@ class Framework(AppwriteModel): buildruntime: str = Field(..., alias='buildRuntime') runtimes: List[Any] = Field(..., alias='runtimes') adapters: List[FrameworkAdapter] = Field(..., alias='adapters') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'name' not in data: + data['name'] = '' + if 'buildRuntime' not in data and 'buildruntime' not in data: + data['buildRuntime'] = '' + if 'runtimes' not in data: + data['runtimes'] = [] + if 'adapters' not in data: + data['adapters'] = [] + return data diff --git a/appwrite/models/framework_adapter.py b/appwrite/models/framework_adapter.py index 1cfac625..5a2a3743 100644 --- a/appwrite/models/framework_adapter.py +++ b/appwrite/models/framework_adapter.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,20 @@ class FrameworkAdapter(AppwriteModel): buildcommand: str = Field(..., alias='buildCommand') outputdirectory: str = Field(..., alias='outputDirectory') fallbackfile: Optional[str] = Field(default=None, alias='fallbackFile') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'installCommand' not in data and 'installcommand' not in data: + data['installCommand'] = '' + if 'buildCommand' not in data and 'buildcommand' not in data: + data['buildCommand'] = '' + if 'outputDirectory' not in data and 'outputdirectory' not in data: + data['outputDirectory'] = '' + return data diff --git a/appwrite/models/framework_list.py b/appwrite/models/framework_list.py index 47ab1244..748c9628 100644 --- a/appwrite/models/framework_list.py +++ b/appwrite/models/framework_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .framework import Framework @@ -19,3 +19,16 @@ class FrameworkList(AppwriteModel): total: float = Field(..., alias='total') frameworks: List[Framework] = Field(..., alias='frameworks') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'frameworks' not in data: + data['frameworks'] = [] + return data diff --git a/appwrite/models/function.py b/appwrite/models/function.py index c080c4bc..87862433 100644 --- a/appwrite/models/function.py +++ b/appwrite/models/function.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .variable import Variable @@ -77,6 +77,8 @@ class Function(AppwriteModel): Machine specification for deployment builds. runtimespecification : str Machine specification for executions. + emailenabled : bool + Whether inbound email (SMTP) may trigger this function. Opt-in; default is false. When disabled, recipients for this function are rejected. """ id: str = Field(..., alias='$id') @@ -112,3 +114,79 @@ class Function(AppwriteModel): providerpaths: List[Any] = Field(..., alias='providerPaths') buildspecification: str = Field(..., alias='buildSpecification') runtimespecification: str = Field(..., alias='runtimeSpecification') + emailenabled: bool = Field(..., alias='emailEnabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'execute' not in data: + data['execute'] = [] + if 'name' not in data: + data['name'] = '' + if 'enabled' not in data: + data['enabled'] = True + if 'live' not in data: + data['live'] = True + if 'logging' not in data: + data['logging'] = True + if 'runtime' not in data: + data['runtime'] = '' + if 'deploymentRetention' not in data and 'deploymentretention' not in data: + data['deploymentRetention'] = 0 + if 'deploymentId' not in data and 'deploymentid' not in data: + data['deploymentId'] = '' + if 'deploymentCreatedAt' not in data and 'deploymentcreatedat' not in data: + data['deploymentCreatedAt'] = '' + if 'latestDeploymentId' not in data and 'latestdeploymentid' not in data: + data['latestDeploymentId'] = '' + if 'latestDeploymentCreatedAt' not in data and 'latestdeploymentcreatedat' not in data: + data['latestDeploymentCreatedAt'] = '' + if 'latestDeploymentStatus' not in data and 'latestdeploymentstatus' not in data: + data['latestDeploymentStatus'] = '' + if 'scopes' not in data: + data['scopes'] = [] + if 'vars' not in data: + data['vars'] = [] + if 'events' not in data: + data['events'] = [] + if 'schedule' not in data: + data['schedule'] = '' + if 'timeout' not in data: + data['timeout'] = 15 + if 'entrypoint' not in data: + data['entrypoint'] = '' + if 'commands' not in data: + data['commands'] = '' + if 'version' not in data: + data['version'] = 'v5' + if 'installationId' not in data and 'installationid' not in data: + data['installationId'] = '' + if 'providerRepositoryId' not in data and 'providerrepositoryid' not in data: + data['providerRepositoryId'] = '' + if 'providerBranch' not in data and 'providerbranch' not in data: + data['providerBranch'] = '' + if 'providerRootDirectory' not in data and 'providerrootdirectory' not in data: + data['providerRootDirectory'] = '' + if 'providerSilentMode' not in data and 'providersilentmode' not in data: + data['providerSilentMode'] = False + if 'providerBranches' not in data and 'providerbranches' not in data: + data['providerBranches'] = [] + if 'providerPaths' not in data and 'providerpaths' not in data: + data['providerPaths'] = [] + if 'buildSpecification' not in data and 'buildspecification' not in data: + data['buildSpecification'] = 's-1vcpu-512mb' + if 'runtimeSpecification' not in data and 'runtimespecification' not in data: + data['runtimeSpecification'] = 's-1vcpu-512mb' + if 'emailEnabled' not in data and 'emailenabled' not in data: + data['emailEnabled'] = False + return data diff --git a/appwrite/models/function_list.py b/appwrite/models/function_list.py index ec302b07..a9f64f3a 100644 --- a/appwrite/models/function_list.py +++ b/appwrite/models/function_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .function import Function @@ -19,3 +19,16 @@ class FunctionList(AppwriteModel): total: float = Field(..., alias='total') functions: List[Function] = Field(..., alias='functions') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'functions' not in data: + data['functions'] = [] + return data diff --git a/appwrite/models/headers.py b/appwrite/models/headers.py index 569f2e9f..301dc02a 100644 --- a/appwrite/models/headers.py +++ b/appwrite/models/headers.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class Headers(AppwriteModel): name: str = Field(..., alias='name') value: str = Field(..., alias='value') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'name' not in data: + data['name'] = '' + if 'value' not in data: + data['value'] = '' + return data diff --git a/appwrite/models/identity.py b/appwrite/models/identity.py index 6a72ebc1..5366f7dd 100644 --- a/appwrite/models/identity.py +++ b/appwrite/models/identity.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -30,7 +30,7 @@ class Identity(AppwriteModel): The date of when the access token expires in ISO 8601 format. providerrefreshtoken : str Identity Provider Refresh Token. - provideridtoken : Optional[str] + provideridtoken : str Identity Provider ID token (JWT) from the most recent native sign-in. Empty for identities created through the browser OAuth2 flow. """ @@ -44,4 +44,35 @@ class Identity(AppwriteModel): provideraccesstoken: str = Field(..., alias='providerAccessToken') provideraccesstokenexpiry: str = Field(..., alias='providerAccessTokenExpiry') providerrefreshtoken: str = Field(..., alias='providerRefreshToken') - provideridtoken: Optional[str] = Field(default=None, alias='providerIdToken') + provideridtoken: str = Field(..., alias='providerIdToken') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'provider' not in data: + data['provider'] = '' + if 'providerUid' not in data and 'provideruid' not in data: + data['providerUid'] = '' + if 'providerEmail' not in data and 'provideremail' not in data: + data['providerEmail'] = '' + if 'providerAccessToken' not in data and 'provideraccesstoken' not in data: + data['providerAccessToken'] = '' + if 'providerAccessTokenExpiry' not in data and 'provideraccesstokenexpiry' not in data: + data['providerAccessTokenExpiry'] = '' + if 'providerRefreshToken' not in data and 'providerrefreshtoken' not in data: + data['providerRefreshToken'] = '' + if 'providerIdToken' not in data and 'provideridtoken' not in data: + data['providerIdToken'] = '' + return data diff --git a/appwrite/models/identity_list.py b/appwrite/models/identity_list.py index ced73450..a2d45ea3 100644 --- a/appwrite/models/identity_list.py +++ b/appwrite/models/identity_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .identity import Identity @@ -19,3 +19,16 @@ class IdentityList(AppwriteModel): total: float = Field(..., alias='total') identities: List[Identity] = Field(..., alias='identities') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'identities' not in data: + data['identities'] = [] + return data diff --git a/appwrite/models/index.py b/appwrite/models/index.py index aea86c9f..21613a19 100644 --- a/appwrite/models/index.py +++ b/appwrite/models/index.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.index_status import IndexStatus @@ -43,3 +43,28 @@ class Index(AppwriteModel): attributes: List[Any] = Field(..., alias='attributes') lengths: List[Any] = Field(..., alias='lengths') orders: Optional[List[Any]] = Field(default=None, alias='orders') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'key' not in data: + data['key'] = '' + if 'type' not in data: + data['type'] = '' + if 'error' not in data: + data['error'] = '' + if 'attributes' not in data: + data['attributes'] = [] + if 'lengths' not in data: + data['lengths'] = [] + return data diff --git a/appwrite/models/index_list.py b/appwrite/models/index_list.py index b9eeab2c..b7075308 100644 --- a/appwrite/models/index_list.py +++ b/appwrite/models/index_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .index import Index @@ -19,3 +19,16 @@ class IndexList(AppwriteModel): total: float = Field(..., alias='total') indexes: List[Index] = Field(..., alias='indexes') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'indexes' not in data: + data['indexes'] = [] + return data diff --git a/appwrite/models/insight.py b/appwrite/models/insight.py index 8c561228..d014db08 100644 --- a/appwrite/models/insight.py +++ b/appwrite/models/insight.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .insight_cta import InsightCTA @@ -64,3 +64,40 @@ class Insight(AppwriteModel): analyzedat: Optional[str] = Field(default=None, alias='analyzedAt') dismissedat: Optional[str] = Field(default=None, alias='dismissedAt') dismissedby: Optional[str] = Field(default=None, alias='dismissedBy') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'reportId' not in data and 'reportid' not in data: + data['reportId'] = '' + if 'type' not in data: + data['type'] = '' + if 'severity' not in data: + data['severity'] = 'info' + if 'status' not in data: + data['status'] = 'active' + if 'resourceType' not in data and 'resourcetype' not in data: + data['resourceType'] = '' + if 'resourceId' not in data and 'resourceid' not in data: + data['resourceId'] = '' + if 'parentResourceType' not in data and 'parentresourcetype' not in data: + data['parentResourceType'] = '' + if 'parentResourceId' not in data and 'parentresourceid' not in data: + data['parentResourceId'] = '' + if 'title' not in data: + data['title'] = '' + if 'summary' not in data: + data['summary'] = '' + if 'ctas' not in data: + data['ctas'] = [] + return data diff --git a/appwrite/models/insight_cta.py b/appwrite/models/insight_cta.py index bc4144f7..4cef545f 100644 --- a/appwrite/models/insight_cta.py +++ b/appwrite/models/insight_cta.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class InsightCTA(AppwriteModel): service: str = Field(..., alias='service') method: str = Field(..., alias='method') params: Dict[str, Any] = Field(..., alias='params') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'label' not in data: + data['label'] = '' + if 'service' not in data: + data['service'] = '' + if 'method' not in data: + data['method'] = '' + if 'params' not in data: + data['params'] = {} + return data diff --git a/appwrite/models/insight_list.py b/appwrite/models/insight_list.py index 1ac76409..808212df 100644 --- a/appwrite/models/insight_list.py +++ b/appwrite/models/insight_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .insight import Insight @@ -19,3 +19,16 @@ class InsightList(AppwriteModel): total: float = Field(..., alias='total') insights: List[Insight] = Field(..., alias='insights') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'insights' not in data: + data['insights'] = [] + return data diff --git a/appwrite/models/jwt.py b/appwrite/models/jwt.py index 4887d305..f51ad977 100644 --- a/appwrite/models/jwt.py +++ b/appwrite/models/jwt.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -15,3 +15,14 @@ class Jwt(AppwriteModel): """ jwt: str = Field(..., alias='jwt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'jwt' not in data: + data['jwt'] = '' + return data diff --git a/appwrite/models/key.py b/appwrite/models/key.py index b47526d9..f8e209fe 100644 --- a/appwrite/models/key.py +++ b/appwrite/models/key.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -39,3 +39,30 @@ class Key(AppwriteModel): secret: str = Field(..., alias='secret') accessedat: str = Field(..., alias='accessedAt') sdks: List[Any] = Field(..., alias='sdks') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'expire' not in data: + data['expire'] = '' + if 'scopes' not in data: + data['scopes'] = [] + if 'secret' not in data: + data['secret'] = '' + if 'accessedAt' not in data and 'accessedat' not in data: + data['accessedAt'] = '' + if 'sdks' not in data: + data['sdks'] = [] + return data diff --git a/appwrite/models/key_list.py b/appwrite/models/key_list.py index 067da645..153c96bb 100644 --- a/appwrite/models/key_list.py +++ b/appwrite/models/key_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .key import Key @@ -19,3 +19,16 @@ class KeyList(AppwriteModel): total: float = Field(..., alias='total') keys: List[Key] = Field(..., alias='keys') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'keys' not in data: + data['keys'] = [] + return data diff --git a/appwrite/models/language.py b/appwrite/models/language.py index 15f23e53..2be89174 100644 --- a/appwrite/models/language.py +++ b/appwrite/models/language.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -21,3 +21,18 @@ class Language(AppwriteModel): name: str = Field(..., alias='name') code: str = Field(..., alias='code') nativename: str = Field(..., alias='nativeName') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'name' not in data: + data['name'] = '' + if 'code' not in data: + data['code'] = '' + if 'nativeName' not in data and 'nativename' not in data: + data['nativeName'] = '' + return data diff --git a/appwrite/models/language_list.py b/appwrite/models/language_list.py index 2e3ff697..7f3cb86b 100644 --- a/appwrite/models/language_list.py +++ b/appwrite/models/language_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .language import Language @@ -19,3 +19,16 @@ class LanguageList(AppwriteModel): total: float = Field(..., alias='total') languages: List[Language] = Field(..., alias='languages') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'languages' not in data: + data['languages'] = [] + return data diff --git a/appwrite/models/locale.py b/appwrite/models/locale.py index 8d9cef21..42767681 100644 --- a/appwrite/models/locale.py +++ b/appwrite/models/locale.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -66,3 +66,26 @@ class Locale(AppwriteModel): connectiontype: Optional[str] = Field(default=None, alias='connectionType') connectionusagetype: Optional[str] = Field(default=None, alias='connectionUsageType') connectionorganization: Optional[str] = Field(default=None, alias='connectionOrganization') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'ip' not in data: + data['ip'] = '' + if 'countryCode' not in data and 'countrycode' not in data: + data['countryCode'] = '' + if 'country' not in data: + data['country'] = '' + if 'continentCode' not in data and 'continentcode' not in data: + data['continentCode'] = '' + if 'continent' not in data: + data['continent'] = '' + if 'eu' not in data: + data['eu'] = False + if 'currency' not in data: + data['currency'] = '' + return data diff --git a/appwrite/models/locale_code.py b/appwrite/models/locale_code.py index 5381c5ec..6656f684 100644 --- a/appwrite/models/locale_code.py +++ b/appwrite/models/locale_code.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class LocaleCode(AppwriteModel): code: str = Field(..., alias='code') name: str = Field(..., alias='name') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'code' not in data: + data['code'] = '' + if 'name' not in data: + data['name'] = '' + return data diff --git a/appwrite/models/locale_code_list.py b/appwrite/models/locale_code_list.py index c80ce4ad..22332f89 100644 --- a/appwrite/models/locale_code_list.py +++ b/appwrite/models/locale_code_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .locale_code import LocaleCode @@ -19,3 +19,16 @@ class LocaleCodeList(AppwriteModel): total: float = Field(..., alias='total') localecodes: List[LocaleCode] = Field(..., alias='localeCodes') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'localeCodes' not in data and 'localecodes' not in data: + data['localeCodes'] = [] + return data diff --git a/appwrite/models/log.py b/appwrite/models/log.py deleted file mode 100644 index a3b74c15..00000000 --- a/appwrite/models/log.py +++ /dev/null @@ -1,80 +0,0 @@ -from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr - -from .base_model import AppwriteModel - - -class Log(AppwriteModel): - """ - Log - - Attributes - ---------- - event : str - Event name. - userid : str - User ID of the actor recorded for this log. During impersonation, this is the original impersonator, not the impersonated target user. - useremail : str - User email of the actor recorded for this log. During impersonation, this is the original impersonator. - username : str - User name of the actor recorded for this log. During impersonation, this is the original impersonator. - mode : str - API mode when event triggered. - usertype : str - User type who triggered the audit log. Possible values: user, admin, guest, hidden, keyProject, keyAccount, keyOrganization. - ip : str - IP session in use when the session was created. - time : str - Log creation date in ISO 8601 format. - oscode : str - Operating system code name. View list of [available options](https://github.com/appwrite/appwrite/blob/master/docs/lists/os.json). - osname : str - Operating system name. - osversion : str - Operating system version. - clienttype : str - Client type. - clientcode : str - Client code name. View list of [available options](https://github.com/appwrite/appwrite/blob/master/docs/lists/clients.json). - clientname : str - Client name. - clientversion : str - Client version. - clientengine : str - Client engine name. - clientengineversion : str - Client engine name. - devicename : str - Device name. - devicebrand : str - Device brand name. - devicemodel : str - Device model name. - countrycode : str - Country two-character ISO 3166-1 alpha code. - countryname : str - Country name. - """ - - event: str = Field(..., alias='event') - userid: str = Field(..., alias='userId') - useremail: str = Field(..., alias='userEmail') - username: str = Field(..., alias='userName') - mode: str = Field(..., alias='mode') - usertype: str = Field(..., alias='userType') - ip: str = Field(..., alias='ip') - time: str = Field(..., alias='time') - oscode: str = Field(..., alias='osCode') - osname: str = Field(..., alias='osName') - osversion: str = Field(..., alias='osVersion') - clienttype: str = Field(..., alias='clientType') - clientcode: str = Field(..., alias='clientCode') - clientname: str = Field(..., alias='clientName') - clientversion: str = Field(..., alias='clientVersion') - clientengine: str = Field(..., alias='clientEngine') - clientengineversion: str = Field(..., alias='clientEngineVersion') - devicename: str = Field(..., alias='deviceName') - devicebrand: str = Field(..., alias='deviceBrand') - devicemodel: str = Field(..., alias='deviceModel') - countrycode: str = Field(..., alias='countryCode') - countryname: str = Field(..., alias='countryName') diff --git a/appwrite/models/log_list.py b/appwrite/models/log_list.py deleted file mode 100644 index 33ff6c77..00000000 --- a/appwrite/models/log_list.py +++ /dev/null @@ -1,21 +0,0 @@ -from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr - -from .base_model import AppwriteModel -from .log import Log - - -class LogList(AppwriteModel): - """ - Logs List - - Attributes - ---------- - total : float - Total number of logs that matched your query. - logs : List[Log] - List of logs. - """ - - total: float = Field(..., alias='total') - logs: List[Log] = Field(..., alias='logs') diff --git a/appwrite/models/membership.py b/appwrite/models/membership.py index 173096ce..810aad13 100644 --- a/appwrite/models/membership.py +++ b/appwrite/models/membership.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -57,3 +57,42 @@ class Membership(AppwriteModel): mfa: bool = Field(..., alias='mfa') useraccessedat: str = Field(..., alias='userAccessedAt') roles: List[Any] = Field(..., alias='roles') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'userName' not in data and 'username' not in data: + data['userName'] = '' + if 'userEmail' not in data and 'useremail' not in data: + data['userEmail'] = '' + if 'userPhone' not in data and 'userphone' not in data: + data['userPhone'] = '' + if 'teamId' not in data and 'teamid' not in data: + data['teamId'] = '' + if 'teamName' not in data and 'teamname' not in data: + data['teamName'] = '' + if 'invited' not in data: + data['invited'] = '' + if 'joined' not in data: + data['joined'] = '' + if 'confirm' not in data: + data['confirm'] = False + if 'mfa' not in data: + data['mfa'] = False + if 'userAccessedAt' not in data and 'useraccessedat' not in data: + data['userAccessedAt'] = '' + if 'roles' not in data: + data['roles'] = [] + return data diff --git a/appwrite/models/membership_list.py b/appwrite/models/membership_list.py index 19f23189..4da824a9 100644 --- a/appwrite/models/membership_list.py +++ b/appwrite/models/membership_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .membership import Membership @@ -19,3 +19,16 @@ class MembershipList(AppwriteModel): total: float = Field(..., alias='total') memberships: List[Membership] = Field(..., alias='memberships') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'memberships' not in data: + data['memberships'] = [] + return data diff --git a/appwrite/models/message.py b/appwrite/models/message.py index 6662583f..85dfc742 100644 --- a/appwrite/models/message.py +++ b/appwrite/models/message.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.message_status import MessageStatus @@ -52,3 +52,32 @@ class Message(AppwriteModel): deliveredtotal: float = Field(..., alias='deliveredTotal') data: Dict[str, Any] = Field(..., alias='data') status: MessageStatus = Field(..., alias='status') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'providerType' not in data and 'providertype' not in data: + data['providerType'] = '' + if 'topics' not in data: + data['topics'] = [] + if 'users' not in data: + data['users'] = [] + if 'targets' not in data: + data['targets'] = [] + if 'deliveredTotal' not in data and 'deliveredtotal' not in data: + data['deliveredTotal'] = 0 + if 'data' not in data: + data['data'] = {} + if 'status' not in data: + data['status'] = 'draft' + return data diff --git a/appwrite/models/message_list.py b/appwrite/models/message_list.py index ffea3f8f..c083f08c 100644 --- a/appwrite/models/message_list.py +++ b/appwrite/models/message_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .message import Message @@ -19,3 +19,16 @@ class MessageList(AppwriteModel): total: float = Field(..., alias='total') messages: List[Message] = Field(..., alias='messages') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'messages' not in data: + data['messages'] = [] + return data diff --git a/appwrite/models/mfa_challenge.py b/appwrite/models/mfa_challenge.py index 5ad1ec9c..6602c6b5 100644 --- a/appwrite/models/mfa_challenge.py +++ b/appwrite/models/mfa_challenge.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class MfaChallenge(AppwriteModel): createdat: str = Field(..., alias='$createdAt') userid: str = Field(..., alias='userId') expire: str = Field(..., alias='expire') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'expire' not in data: + data['expire'] = '' + return data diff --git a/appwrite/models/mfa_challenge_secret.py b/appwrite/models/mfa_challenge_secret.py index e9a03fb1..2eab2511 100644 --- a/appwrite/models/mfa_challenge_secret.py +++ b/appwrite/models/mfa_challenge_secret.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,22 @@ class MfaChallengeSecret(AppwriteModel): userid: str = Field(..., alias='userId') expire: str = Field(..., alias='expire') code: str = Field(..., alias='code') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'expire' not in data: + data['expire'] = '' + if 'code' not in data: + data['code'] = '' + return data diff --git a/appwrite/models/mfa_factors.py b/appwrite/models/mfa_factors.py index 24810f03..a11ca15a 100644 --- a/appwrite/models/mfa_factors.py +++ b/appwrite/models/mfa_factors.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,22 @@ class MfaFactors(AppwriteModel): email: bool = Field(..., alias='email') recoverycode: bool = Field(..., alias='recoveryCode') custom: bool = Field(..., alias='custom') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'totp' not in data: + data['totp'] = False + if 'phone' not in data: + data['phone'] = False + if 'email' not in data: + data['email'] = False + if 'recoveryCode' not in data and 'recoverycode' not in data: + data['recoveryCode'] = False + if 'custom' not in data: + data['custom'] = False + return data diff --git a/appwrite/models/mfa_recovery_codes.py b/appwrite/models/mfa_recovery_codes.py index e64bf853..52ff1d66 100644 --- a/appwrite/models/mfa_recovery_codes.py +++ b/appwrite/models/mfa_recovery_codes.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -15,3 +15,14 @@ class MfaRecoveryCodes(AppwriteModel): """ recoverycodes: List[Any] = Field(..., alias='recoveryCodes') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'recoveryCodes' not in data and 'recoverycodes' not in data: + data['recoveryCodes'] = [] + return data diff --git a/appwrite/models/mfa_type.py b/appwrite/models/mfa_type.py index 5d6bb5e9..1afba454 100644 --- a/appwrite/models/mfa_type.py +++ b/appwrite/models/mfa_type.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class MfaType(AppwriteModel): secret: str = Field(..., alias='secret') uri: str = Field(..., alias='uri') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'secret' not in data: + data['secret'] = '' + if 'uri' not in data: + data['uri'] = '' + return data diff --git a/appwrite/models/mock_number.py b/appwrite/models/mock_number.py index 9e6f09cc..5e63da1b 100644 --- a/appwrite/models/mock_number.py +++ b/appwrite/models/mock_number.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class MockNumber(AppwriteModel): otp: str = Field(..., alias='otp') createdat: str = Field(..., alias='$createdAt') updatedat: str = Field(..., alias='$updatedAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'number' not in data: + data['number'] = '' + if 'otp' not in data: + data['otp'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + return data diff --git a/appwrite/models/mock_number_list.py b/appwrite/models/mock_number_list.py index ae29efe9..e7ab46a0 100644 --- a/appwrite/models/mock_number_list.py +++ b/appwrite/models/mock_number_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .mock_number import MockNumber @@ -19,3 +19,16 @@ class MockNumberList(AppwriteModel): total: float = Field(..., alias='total') mocknumbers: List[MockNumber] = Field(..., alias='mockNumbers') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'mockNumbers' not in data and 'mocknumbers' not in data: + data['mockNumbers'] = [] + return data diff --git a/appwrite/models/o_auth2_amazon.py b/appwrite/models/o_auth2_amazon.py index aad2ebb3..4d7b7b9a 100644 --- a/appwrite/models/o_auth2_amazon.py +++ b/appwrite/models/o_auth2_amazon.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Amazon(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_apple.py b/appwrite/models/o_auth2_apple.py index c31f8062..4acb8fbc 100644 --- a/appwrite/models/o_auth2_apple.py +++ b/appwrite/models/o_auth2_apple.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -22,9 +22,9 @@ class OAuth2Apple(AppwriteModel): Apple OAuth2 team ID. p8file : str Apple OAuth2 .p8 private key file contents. The secret key wrapped by the PEM markers is 200 characters long. - nativeenabled : Optional[bool] + nativeenabled : bool Native Sign in with Apple is active and can be used to create sessions from an ID token. Independent of enabled, which only controls the browser-based flow. - nativeclientids : Optional[List[Any]] + nativeclientids : List[Any] App bundle IDs accepted as ID token audiences for native Sign in with Apple, next to the Services ID. """ @@ -34,5 +34,30 @@ class OAuth2Apple(AppwriteModel): keyid: str = Field(..., alias='keyId') teamid: str = Field(..., alias='teamId') p8file: str = Field(..., alias='p8File') - nativeenabled: Optional[bool] = Field(default=None, alias='nativeEnabled') - nativeclientids: Optional[List[Any]] = Field(default=None, alias='nativeClientIds') + nativeenabled: bool = Field(..., alias='nativeEnabled') + nativeclientids: List[Any] = Field(..., alias='nativeClientIds') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'serviceId' not in data and 'serviceid' not in data: + data['serviceId'] = '' + if 'keyId' not in data and 'keyid' not in data: + data['keyId'] = '' + if 'teamId' not in data and 'teamid' not in data: + data['teamId'] = '' + if 'p8File' not in data and 'p8file' not in data: + data['p8File'] = '' + if 'nativeEnabled' not in data and 'nativeenabled' not in data: + data['nativeEnabled'] = False + if 'nativeClientIds' not in data and 'nativeclientids' not in data: + data['nativeClientIds'] = [] + return data diff --git a/appwrite/models/o_auth2_appwrite.py b/appwrite/models/o_auth2_appwrite.py index 7d5f4a34..f80a0bb8 100644 --- a/appwrite/models/o_auth2_appwrite.py +++ b/appwrite/models/o_auth2_appwrite.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Appwrite(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_auth0.py b/appwrite/models/o_auth2_auth0.py index 776341f7..d27f4797 100644 --- a/appwrite/models/o_auth2_auth0.py +++ b/appwrite/models/o_auth2_auth0.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.o_auth2_auth0_prompt import OAuth2Auth0Prompt @@ -19,7 +19,7 @@ class OAuth2Auth0(AppwriteModel): Auth0 OAuth2 client ID. clientsecret : str Auth0 OAuth2 client secret. - prompt : Optional[List[OAuth2Auth0Prompt]] + prompt : List[OAuth2Auth0Prompt] Auth0 OAuth2 prompt values. endpoint : str Auth0 OAuth2 endpoint domain. @@ -29,5 +29,26 @@ class OAuth2Auth0(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') - prompt: Optional[List[OAuth2Auth0Prompt]] = Field(default=None, alias='prompt') + prompt: List[OAuth2Auth0Prompt] = Field(..., alias='prompt') endpoint: str = Field(..., alias='endpoint') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + if 'prompt' not in data: + data['prompt'] = [] + if 'endpoint' not in data: + data['endpoint'] = '' + return data diff --git a/appwrite/models/o_auth2_authentik.py b/appwrite/models/o_auth2_authentik.py index 917c67eb..12e29212 100644 --- a/appwrite/models/o_auth2_authentik.py +++ b/appwrite/models/o_auth2_authentik.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,22 @@ class OAuth2Authentik(AppwriteModel): clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') endpoint: str = Field(..., alias='endpoint') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + if 'endpoint' not in data: + data['endpoint'] = '' + return data diff --git a/appwrite/models/o_auth2_autodesk.py b/appwrite/models/o_auth2_autodesk.py index 69bf0aba..d58de659 100644 --- a/appwrite/models/o_auth2_autodesk.py +++ b/appwrite/models/o_auth2_autodesk.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Autodesk(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_bitbucket.py b/appwrite/models/o_auth2_bitbucket.py index a62d0979..247f3b9c 100644 --- a/appwrite/models/o_auth2_bitbucket.py +++ b/appwrite/models/o_auth2_bitbucket.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Bitbucket(AppwriteModel): enabled: bool = Field(..., alias='enabled') key: str = Field(..., alias='key') secret: str = Field(..., alias='secret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'key' not in data: + data['key'] = '' + if 'secret' not in data: + data['secret'] = '' + return data diff --git a/appwrite/models/o_auth2_bitly.py b/appwrite/models/o_auth2_bitly.py index f3284f4b..00e893ed 100644 --- a/appwrite/models/o_auth2_bitly.py +++ b/appwrite/models/o_auth2_bitly.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Bitly(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_box.py b/appwrite/models/o_auth2_box.py index f64f0140..492bc38d 100644 --- a/appwrite/models/o_auth2_box.py +++ b/appwrite/models/o_auth2_box.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Box(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_cloudflare.py b/appwrite/models/o_auth2_cloudflare.py index 5099f214..5d977c6e 100644 --- a/appwrite/models/o_auth2_cloudflare.py +++ b/appwrite/models/o_auth2_cloudflare.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Cloudflare(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_dailymotion.py b/appwrite/models/o_auth2_dailymotion.py index fa1836c3..d8e3ece8 100644 --- a/appwrite/models/o_auth2_dailymotion.py +++ b/appwrite/models/o_auth2_dailymotion.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Dailymotion(AppwriteModel): enabled: bool = Field(..., alias='enabled') apikey: str = Field(..., alias='apiKey') apisecret: str = Field(..., alias='apiSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'apiKey' not in data and 'apikey' not in data: + data['apiKey'] = '' + if 'apiSecret' not in data and 'apisecret' not in data: + data['apiSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_discord.py b/appwrite/models/o_auth2_discord.py index d3f068cb..0921e557 100644 --- a/appwrite/models/o_auth2_discord.py +++ b/appwrite/models/o_auth2_discord.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.o_auth2_discord_prompt import OAuth2DiscordPrompt @@ -19,7 +19,7 @@ class OAuth2Discord(AppwriteModel): Discord OAuth2 client ID. clientsecret : str Discord OAuth2 client secret. - prompt : Optional[List[OAuth2DiscordPrompt]] + prompt : List[OAuth2DiscordPrompt] Discord OAuth2 prompt values. """ @@ -27,4 +27,23 @@ class OAuth2Discord(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') - prompt: Optional[List[OAuth2DiscordPrompt]] = Field(default=None, alias='prompt') + prompt: List[OAuth2DiscordPrompt] = Field(..., alias='prompt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + if 'prompt' not in data: + data['prompt'] = [] + return data diff --git a/appwrite/models/o_auth2_disqus.py b/appwrite/models/o_auth2_disqus.py index 302fc486..f534f160 100644 --- a/appwrite/models/o_auth2_disqus.py +++ b/appwrite/models/o_auth2_disqus.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Disqus(AppwriteModel): enabled: bool = Field(..., alias='enabled') publickey: str = Field(..., alias='publicKey') secretkey: str = Field(..., alias='secretKey') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'publicKey' not in data and 'publickey' not in data: + data['publicKey'] = '' + if 'secretKey' not in data and 'secretkey' not in data: + data['secretKey'] = '' + return data diff --git a/appwrite/models/o_auth2_dropbox.py b/appwrite/models/o_auth2_dropbox.py index d8b980f8..1e598082 100644 --- a/appwrite/models/o_auth2_dropbox.py +++ b/appwrite/models/o_auth2_dropbox.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Dropbox(AppwriteModel): enabled: bool = Field(..., alias='enabled') appkey: str = Field(..., alias='appKey') appsecret: str = Field(..., alias='appSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'appKey' not in data and 'appkey' not in data: + data['appKey'] = '' + if 'appSecret' not in data and 'appsecret' not in data: + data['appSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_etsy.py b/appwrite/models/o_auth2_etsy.py index 9b3b7480..8226ae65 100644 --- a/appwrite/models/o_auth2_etsy.py +++ b/appwrite/models/o_auth2_etsy.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Etsy(AppwriteModel): enabled: bool = Field(..., alias='enabled') keystring: str = Field(..., alias='keyString') sharedsecret: str = Field(..., alias='sharedSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'keyString' not in data and 'keystring' not in data: + data['keyString'] = '' + if 'sharedSecret' not in data and 'sharedsecret' not in data: + data['sharedSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_facebook.py b/appwrite/models/o_auth2_facebook.py index 83e72aa5..640ca559 100644 --- a/appwrite/models/o_auth2_facebook.py +++ b/appwrite/models/o_auth2_facebook.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Facebook(AppwriteModel): enabled: bool = Field(..., alias='enabled') appid: str = Field(..., alias='appId') appsecret: str = Field(..., alias='appSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'appId' not in data and 'appid' not in data: + data['appId'] = '' + if 'appSecret' not in data and 'appsecret' not in data: + data['appSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_figma.py b/appwrite/models/o_auth2_figma.py index 3ad1bb66..5c650b1b 100644 --- a/appwrite/models/o_auth2_figma.py +++ b/appwrite/models/o_auth2_figma.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Figma(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_fusion_auth.py b/appwrite/models/o_auth2_fusion_auth.py index b38e63a3..25d57023 100644 --- a/appwrite/models/o_auth2_fusion_auth.py +++ b/appwrite/models/o_auth2_fusion_auth.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,22 @@ class OAuth2FusionAuth(AppwriteModel): clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') endpoint: str = Field(..., alias='endpoint') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + if 'endpoint' not in data: + data['endpoint'] = '' + return data diff --git a/appwrite/models/o_auth2_github.py b/appwrite/models/o_auth2_github.py index d326ffe2..e8305891 100644 --- a/appwrite/models/o_auth2_github.py +++ b/appwrite/models/o_auth2_github.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.o_auth2_github_prompt import OAuth2GithubPrompt @@ -19,7 +19,7 @@ class OAuth2Github(AppwriteModel): GitHub OAuth2 client ID. For GitHub Apps, use the "App ID" when both an App ID and client ID are available. clientsecret : str GitHub OAuth2 client secret. - prompt : Optional[List[OAuth2GithubPrompt]] + prompt : List[OAuth2GithubPrompt] GitHub OAuth2 prompt values. """ @@ -27,4 +27,23 @@ class OAuth2Github(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') - prompt: Optional[List[OAuth2GithubPrompt]] = Field(default=None, alias='prompt') + prompt: List[OAuth2GithubPrompt] = Field(..., alias='prompt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + if 'prompt' not in data: + data['prompt'] = [] + return data diff --git a/appwrite/models/o_auth2_gitlab.py b/appwrite/models/o_auth2_gitlab.py index 3014d836..2c61563f 100644 --- a/appwrite/models/o_auth2_gitlab.py +++ b/appwrite/models/o_auth2_gitlab.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,22 @@ class OAuth2Gitlab(AppwriteModel): applicationid: str = Field(..., alias='applicationId') secret: str = Field(..., alias='secret') endpoint: str = Field(..., alias='endpoint') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'applicationId' not in data and 'applicationid' not in data: + data['applicationId'] = '' + if 'secret' not in data: + data['secret'] = '' + if 'endpoint' not in data: + data['endpoint'] = '' + return data diff --git a/appwrite/models/o_auth2_google.py b/appwrite/models/o_auth2_google.py index 2bfd961c..8a77adf6 100644 --- a/appwrite/models/o_auth2_google.py +++ b/appwrite/models/o_auth2_google.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.o_auth2_google_prompt import OAuth2GooglePrompt @@ -21,9 +21,9 @@ class OAuth2Google(AppwriteModel): Google OAuth2 client secret. prompt : List[OAuth2GooglePrompt] Google OAuth2 prompt values. - nativeenabled : Optional[bool] + nativeenabled : bool Native Google sign-in is active and can be used to create sessions from an ID token. Independent of enabled, which only controls the browser-based flow. - nativeclientids : Optional[List[Any]] + nativeclientids : List[Any] Additional OAuth2 client IDs accepted as ID token audiences for native sign-in, next to the client ID. """ @@ -32,5 +32,28 @@ class OAuth2Google(AppwriteModel): clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') prompt: List[OAuth2GooglePrompt] = Field(..., alias='prompt') - nativeenabled: Optional[bool] = Field(default=None, alias='nativeEnabled') - nativeclientids: Optional[List[Any]] = Field(default=None, alias='nativeClientIds') + nativeenabled: bool = Field(..., alias='nativeEnabled') + nativeclientids: List[Any] = Field(..., alias='nativeClientIds') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + if 'prompt' not in data: + data['prompt'] = ['consent'] + if 'nativeEnabled' not in data and 'nativeenabled' not in data: + data['nativeEnabled'] = False + if 'nativeClientIds' not in data and 'nativeclientids' not in data: + data['nativeClientIds'] = [] + return data diff --git a/appwrite/models/o_auth2_hugging_face.py b/appwrite/models/o_auth2_hugging_face.py index d35f9946..80dd65ad 100644 --- a/appwrite/models/o_auth2_hugging_face.py +++ b/appwrite/models/o_auth2_hugging_face.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2HuggingFace(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_kakao.py b/appwrite/models/o_auth2_kakao.py index 4918af5c..0277a6e7 100644 --- a/appwrite/models/o_auth2_kakao.py +++ b/appwrite/models/o_auth2_kakao.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.o_auth2_kakao_prompt import OAuth2KakaoPrompt @@ -28,3 +28,22 @@ class OAuth2Kakao(AppwriteModel): clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') prompt: List[OAuth2KakaoPrompt] = Field(..., alias='prompt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + if 'prompt' not in data: + data['prompt'] = [] + return data diff --git a/appwrite/models/o_auth2_keycloak.py b/appwrite/models/o_auth2_keycloak.py index 674cfae4..941e44ca 100644 --- a/appwrite/models/o_auth2_keycloak.py +++ b/appwrite/models/o_auth2_keycloak.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -30,3 +30,24 @@ class OAuth2Keycloak(AppwriteModel): clientsecret: str = Field(..., alias='clientSecret') endpoint: str = Field(..., alias='endpoint') realmname: str = Field(..., alias='realmName') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + if 'endpoint' not in data: + data['endpoint'] = '' + if 'realmName' not in data and 'realmname' not in data: + data['realmName'] = '' + return data diff --git a/appwrite/models/o_auth2_kick.py b/appwrite/models/o_auth2_kick.py index 2ef797ed..1615abac 100644 --- a/appwrite/models/o_auth2_kick.py +++ b/appwrite/models/o_auth2_kick.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Kick(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_linkedin.py b/appwrite/models/o_auth2_linkedin.py index 62bc6d11..7ebf1b76 100644 --- a/appwrite/models/o_auth2_linkedin.py +++ b/appwrite/models/o_auth2_linkedin.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Linkedin(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') primaryclientsecret: str = Field(..., alias='primaryClientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'primaryClientSecret' not in data and 'primaryclientsecret' not in data: + data['primaryClientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_microsoft.py b/appwrite/models/o_auth2_microsoft.py index 622a530d..5b3461cf 100644 --- a/appwrite/models/o_auth2_microsoft.py +++ b/appwrite/models/o_auth2_microsoft.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.o_auth2_microsoft_prompt import OAuth2MicrosoftPrompt @@ -19,7 +19,7 @@ class OAuth2Microsoft(AppwriteModel): Microsoft OAuth2 application ID. applicationsecret : str Microsoft OAuth2 application secret. - prompt : Optional[List[OAuth2MicrosoftPrompt]] + prompt : List[OAuth2MicrosoftPrompt] Microsoft OAuth2 prompt values. tenant : str Microsoft Entra ID tenant identifier. Use 'common', 'organizations', 'consumers' or a specific tenant ID. @@ -29,5 +29,26 @@ class OAuth2Microsoft(AppwriteModel): enabled: bool = Field(..., alias='enabled') applicationid: str = Field(..., alias='applicationId') applicationsecret: str = Field(..., alias='applicationSecret') - prompt: Optional[List[OAuth2MicrosoftPrompt]] = Field(default=None, alias='prompt') + prompt: List[OAuth2MicrosoftPrompt] = Field(..., alias='prompt') tenant: str = Field(..., alias='tenant') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'applicationId' not in data and 'applicationid' not in data: + data['applicationId'] = '' + if 'applicationSecret' not in data and 'applicationsecret' not in data: + data['applicationSecret'] = '' + if 'prompt' not in data: + data['prompt'] = [] + if 'tenant' not in data: + data['tenant'] = '' + return data diff --git a/appwrite/models/o_auth2_notion.py b/appwrite/models/o_auth2_notion.py index 8ce2bad2..d36eced4 100644 --- a/appwrite/models/o_auth2_notion.py +++ b/appwrite/models/o_auth2_notion.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Notion(AppwriteModel): enabled: bool = Field(..., alias='enabled') oauthclientid: str = Field(..., alias='oauthClientId') oauthclientsecret: str = Field(..., alias='oauthClientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'oauthClientId' not in data and 'oauthclientid' not in data: + data['oauthClientId'] = '' + if 'oauthClientSecret' not in data and 'oauthclientsecret' not in data: + data['oauthClientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_oidc.py b/appwrite/models/o_auth2_oidc.py index d2b65571..0024b934 100644 --- a/appwrite/models/o_auth2_oidc.py +++ b/appwrite/models/o_auth2_oidc.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.o_auth2_oidc_prompt import OAuth2OidcPrompt @@ -19,6 +19,8 @@ class OAuth2Oidc(AppwriteModel): OpenID Connect OAuth2 client ID. clientsecret : str OpenID Connect OAuth2 client secret. + prompt : List[OAuth2OidcPrompt] + OpenID Connect prompt values controlling the authentication and consent screens. wellknownurl : str OpenID Connect well-known configuration URL. When set, authorization, token, and user info endpoints can be discovered automatically. authorizationurl : str @@ -27,8 +29,6 @@ class OAuth2Oidc(AppwriteModel): OpenID Connect token endpoint URL. userinfourl : str OpenID Connect user info endpoint URL. - prompt : List[OAuth2OidcPrompt] - OpenID Connect prompt values controlling the authentication and consent screens. maxage : Optional[float] Maximum authentication age in seconds. When set, the user must have authenticated within this many seconds. """ @@ -37,9 +37,36 @@ class OAuth2Oidc(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + prompt: List[OAuth2OidcPrompt] = Field(..., alias='prompt') wellknownurl: str = Field(..., alias='wellKnownURL') authorizationurl: str = Field(..., alias='authorizationURL') tokenurl: str = Field(..., alias='tokenURL') userinfourl: str = Field(..., alias='userInfoURL') - prompt: List[OAuth2OidcPrompt] = Field(..., alias='prompt') maxage: Optional[float] = Field(default=None, alias='maxAge') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + if 'prompt' not in data: + data['prompt'] = [] + if 'wellKnownURL' not in data and 'wellknownurl' not in data: + data['wellKnownURL'] = '' + if 'authorizationURL' not in data and 'authorizationurl' not in data: + data['authorizationURL'] = '' + if 'tokenURL' not in data and 'tokenurl' not in data: + data['tokenURL'] = '' + if 'userInfoURL' not in data and 'userinfourl' not in data: + data['userInfoURL'] = '' + return data diff --git a/appwrite/models/o_auth2_okta.py b/appwrite/models/o_auth2_okta.py index e64c6af1..d07ff410 100644 --- a/appwrite/models/o_auth2_okta.py +++ b/appwrite/models/o_auth2_okta.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.o_auth2_okta_prompt import OAuth2OktaPrompt @@ -19,7 +19,7 @@ class OAuth2Okta(AppwriteModel): Okta OAuth2 client ID. clientsecret : str Okta OAuth2 client secret. - prompt : Optional[List[OAuth2OktaPrompt]] + prompt : List[OAuth2OktaPrompt] Okta OAuth2 prompt values. domain : str Okta OAuth2 domain. @@ -31,6 +31,29 @@ class OAuth2Okta(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') - prompt: Optional[List[OAuth2OktaPrompt]] = Field(default=None, alias='prompt') + prompt: List[OAuth2OktaPrompt] = Field(..., alias='prompt') domain: str = Field(..., alias='domain') authorizationserverid: str = Field(..., alias='authorizationServerId') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + if 'prompt' not in data: + data['prompt'] = [] + if 'domain' not in data: + data['domain'] = '' + if 'authorizationServerId' not in data and 'authorizationserverid' not in data: + data['authorizationServerId'] = '' + return data diff --git a/appwrite/models/o_auth2_paypal.py b/appwrite/models/o_auth2_paypal.py index a87cb0f8..d5fda507 100644 --- a/appwrite/models/o_auth2_paypal.py +++ b/appwrite/models/o_auth2_paypal.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Paypal(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') secretkey: str = Field(..., alias='secretKey') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'secretKey' not in data and 'secretkey' not in data: + data['secretKey'] = '' + return data diff --git a/appwrite/models/o_auth2_podio.py b/appwrite/models/o_auth2_podio.py index 79b256c7..f533a4a6 100644 --- a/appwrite/models/o_auth2_podio.py +++ b/appwrite/models/o_auth2_podio.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Podio(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_provider_list.py b/appwrite/models/o_auth2_provider_list.py index eaf62fb9..6d2fa3ec 100644 --- a/appwrite/models/o_auth2_provider_list.py +++ b/appwrite/models/o_auth2_provider_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .o_auth2_github import OAuth2Github @@ -115,3 +115,16 @@ class OAuth2ProviderList(AppwriteModel): OAuth2Kakao, ] ] = Field(..., alias='providers') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'providers' not in data: + data['providers'] = [] + return data diff --git a/appwrite/models/o_auth2_resend.py b/appwrite/models/o_auth2_resend.py index 0c3efb05..6209c774 100644 --- a/appwrite/models/o_auth2_resend.py +++ b/appwrite/models/o_auth2_resend.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Resend(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_salesforce.py b/appwrite/models/o_auth2_salesforce.py index 579fb837..fde028a4 100644 --- a/appwrite/models/o_auth2_salesforce.py +++ b/appwrite/models/o_auth2_salesforce.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.o_auth2_salesforce_prompt import OAuth2SalesforcePrompt @@ -19,7 +19,7 @@ class OAuth2Salesforce(AppwriteModel): Salesforce OAuth2 consumer key. customersecret : str Salesforce OAuth2 consumer secret. - prompt : Optional[List[OAuth2SalesforcePrompt]] + prompt : List[OAuth2SalesforcePrompt] Salesforce OAuth2 prompt values. """ @@ -27,4 +27,23 @@ class OAuth2Salesforce(AppwriteModel): enabled: bool = Field(..., alias='enabled') customerkey: str = Field(..., alias='customerKey') customersecret: str = Field(..., alias='customerSecret') - prompt: Optional[List[OAuth2SalesforcePrompt]] = Field(default=None, alias='prompt') + prompt: List[OAuth2SalesforcePrompt] = Field(..., alias='prompt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'customerKey' not in data and 'customerkey' not in data: + data['customerKey'] = '' + if 'customerSecret' not in data and 'customersecret' not in data: + data['customerSecret'] = '' + if 'prompt' not in data: + data['prompt'] = [] + return data diff --git a/appwrite/models/o_auth2_slack.py b/appwrite/models/o_auth2_slack.py index 220df0cc..b5a0bb58 100644 --- a/appwrite/models/o_auth2_slack.py +++ b/appwrite/models/o_auth2_slack.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Slack(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_spotify.py b/appwrite/models/o_auth2_spotify.py index e46d9355..17108a75 100644 --- a/appwrite/models/o_auth2_spotify.py +++ b/appwrite/models/o_auth2_spotify.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Spotify(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_stripe.py b/appwrite/models/o_auth2_stripe.py index c44a8727..bedfef2d 100644 --- a/appwrite/models/o_auth2_stripe.py +++ b/appwrite/models/o_auth2_stripe.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Stripe(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') apisecretkey: str = Field(..., alias='apiSecretKey') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'apiSecretKey' not in data and 'apisecretkey' not in data: + data['apiSecretKey'] = '' + return data diff --git a/appwrite/models/o_auth2_tik_tok.py b/appwrite/models/o_auth2_tik_tok.py index f1d08f68..8a35b76b 100644 --- a/appwrite/models/o_auth2_tik_tok.py +++ b/appwrite/models/o_auth2_tik_tok.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2TikTok(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_tradeshift.py b/appwrite/models/o_auth2_tradeshift.py index 284c2764..834f81f7 100644 --- a/appwrite/models/o_auth2_tradeshift.py +++ b/appwrite/models/o_auth2_tradeshift.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Tradeshift(AppwriteModel): enabled: bool = Field(..., alias='enabled') oauth2clientid: str = Field(..., alias='oauth2ClientId') oauth2clientsecret: str = Field(..., alias='oauth2ClientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'oauth2ClientId' not in data and 'oauth2clientid' not in data: + data['oauth2ClientId'] = '' + if 'oauth2ClientSecret' not in data and 'oauth2clientsecret' not in data: + data['oauth2ClientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_twitch.py b/appwrite/models/o_auth2_twitch.py index 41b51d14..35188582 100644 --- a/appwrite/models/o_auth2_twitch.py +++ b/appwrite/models/o_auth2_twitch.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Twitch(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_webflow.py b/appwrite/models/o_auth2_webflow.py index bf6891ab..b1e2fe02 100644 --- a/appwrite/models/o_auth2_webflow.py +++ b/appwrite/models/o_auth2_webflow.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Webflow(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_word_press.py b/appwrite/models/o_auth2_word_press.py index 64abedaf..5b289c19 100644 --- a/appwrite/models/o_auth2_word_press.py +++ b/appwrite/models/o_auth2_word_press.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2WordPress(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_x.py b/appwrite/models/o_auth2_x.py index 8dfeb6d3..f4299708 100644 --- a/appwrite/models/o_auth2_x.py +++ b/appwrite/models/o_auth2_x.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2X(AppwriteModel): enabled: bool = Field(..., alias='enabled') customerkey: str = Field(..., alias='customerKey') secretkey: str = Field(..., alias='secretKey') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'customerKey' not in data and 'customerkey' not in data: + data['customerKey'] = '' + if 'secretKey' not in data and 'secretkey' not in data: + data['secretKey'] = '' + return data diff --git a/appwrite/models/o_auth2_yahoo.py b/appwrite/models/o_auth2_yahoo.py index f1c4a518..0c0f8be9 100644 --- a/appwrite/models/o_auth2_yahoo.py +++ b/appwrite/models/o_auth2_yahoo.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Yahoo(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_yandex.py b/appwrite/models/o_auth2_yandex.py index c0c93f1a..de65d949 100644 --- a/appwrite/models/o_auth2_yandex.py +++ b/appwrite/models/o_auth2_yandex.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Yandex(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/o_auth2_zoho.py b/appwrite/models/o_auth2_zoho.py index f3ceb99c..f1ecd743 100644 --- a/appwrite/models/o_auth2_zoho.py +++ b/appwrite/models/o_auth2_zoho.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.o_auth2_zoho_prompt import OAuth2ZohoPrompt @@ -19,7 +19,7 @@ class OAuth2Zoho(AppwriteModel): Zoho OAuth2 client ID. clientsecret : str Zoho OAuth2 client secret. - prompt : Optional[List[OAuth2ZohoPrompt]] + prompt : List[OAuth2ZohoPrompt] Zoho OAuth2 prompt values. """ @@ -27,4 +27,23 @@ class OAuth2Zoho(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') - prompt: Optional[List[OAuth2ZohoPrompt]] = Field(default=None, alias='prompt') + prompt: List[OAuth2ZohoPrompt] = Field(..., alias='prompt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + if 'prompt' not in data: + data['prompt'] = [] + return data diff --git a/appwrite/models/o_auth2_zoom.py b/appwrite/models/o_auth2_zoom.py index 4770761e..384e019d 100644 --- a/appwrite/models/o_auth2_zoom.py +++ b/appwrite/models/o_auth2_zoom.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class OAuth2Zoom(AppwriteModel): enabled: bool = Field(..., alias='enabled') clientid: str = Field(..., alias='clientId') clientsecret: str = Field(..., alias='clientSecret') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'clientId' not in data and 'clientid' not in data: + data['clientId'] = '' + if 'clientSecret' not in data and 'clientsecret' not in data: + data['clientSecret'] = '' + return data diff --git a/appwrite/models/oauth2_approve.py b/appwrite/models/oauth2_approve.py index 48b41a9f..fe22f795 100644 --- a/appwrite/models/oauth2_approve.py +++ b/appwrite/models/oauth2_approve.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -15,3 +15,14 @@ class Oauth2Approve(AppwriteModel): """ redirecturl: str = Field(..., alias='redirectUrl') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'redirectUrl' not in data and 'redirecturl' not in data: + data['redirectUrl'] = '' + return data diff --git a/appwrite/models/oauth2_authorize.py b/appwrite/models/oauth2_authorize.py index 34c09c30..4cd1200e 100644 --- a/appwrite/models/oauth2_authorize.py +++ b/appwrite/models/oauth2_authorize.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class Oauth2Authorize(AppwriteModel): grantid: str = Field(..., alias='grantId') redirecturl: str = Field(..., alias='redirectUrl') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'grantId' not in data and 'grantid' not in data: + data['grantId'] = '' + if 'redirectUrl' not in data and 'redirecturl' not in data: + data['redirectUrl'] = '' + return data diff --git a/appwrite/models/oauth2_consent.py b/appwrite/models/oauth2_consent.py index 22b5805a..71f31bfb 100644 --- a/appwrite/models/oauth2_consent.py +++ b/appwrite/models/oauth2_consent.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -42,3 +42,32 @@ class Oauth2Consent(AppwriteModel): resources: List[Any] = Field(..., alias='resources') authorizationdetails: str = Field(..., alias='authorizationDetails') expire: str = Field(..., alias='expire') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'appId' not in data and 'appid' not in data: + data['appId'] = '' + if 'cimdUrl' not in data and 'cimdurl' not in data: + data['cimdUrl'] = '' + if 'scopes' not in data: + data['scopes'] = [] + if 'resources' not in data: + data['resources'] = [] + if 'authorizationDetails' not in data and 'authorizationdetails' not in data: + data['authorizationDetails'] = '[]' + if 'expire' not in data: + data['expire'] = '' + return data diff --git a/appwrite/models/oauth2_consent_list.py b/appwrite/models/oauth2_consent_list.py index cf1ded74..9462b55d 100644 --- a/appwrite/models/oauth2_consent_list.py +++ b/appwrite/models/oauth2_consent_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .oauth2_consent import Oauth2Consent @@ -19,3 +19,16 @@ class Oauth2ConsentList(AppwriteModel): total: float = Field(..., alias='total') consents: List[Oauth2Consent] = Field(..., alias='consents') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'consents' not in data: + data['consents'] = [] + return data diff --git a/appwrite/models/oauth2_consent_token.py b/appwrite/models/oauth2_consent_token.py index 022d826d..ae91a095 100644 --- a/appwrite/models/oauth2_consent_token.py +++ b/appwrite/models/oauth2_consent_token.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -45,3 +45,34 @@ class Oauth2ConsentToken(AppwriteModel): resources: List[Any] = Field(..., alias='resources') authorizationdetails: str = Field(..., alias='authorizationDetails') expire: str = Field(..., alias='expire') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'consentId' not in data and 'consentid' not in data: + data['consentId'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'appId' not in data and 'appid' not in data: + data['appId'] = '' + if 'cimdUrl' not in data and 'cimdurl' not in data: + data['cimdUrl'] = '' + if 'scopes' not in data: + data['scopes'] = [] + if 'resources' not in data: + data['resources'] = [] + if 'authorizationDetails' not in data and 'authorizationdetails' not in data: + data['authorizationDetails'] = '[]' + if 'expire' not in data: + data['expire'] = '' + return data diff --git a/appwrite/models/oauth2_consent_token_list.py b/appwrite/models/oauth2_consent_token_list.py index d64c366d..daa22676 100644 --- a/appwrite/models/oauth2_consent_token_list.py +++ b/appwrite/models/oauth2_consent_token_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .oauth2_consent_token import Oauth2ConsentToken @@ -19,3 +19,16 @@ class Oauth2ConsentTokenList(AppwriteModel): total: float = Field(..., alias='total') tokens: List[Oauth2ConsentToken] = Field(..., alias='tokens') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'tokens' not in data: + data['tokens'] = [] + return data diff --git a/appwrite/models/oauth2_device_authorization.py b/appwrite/models/oauth2_device_authorization.py index 4d423857..df9f9d30 100644 --- a/appwrite/models/oauth2_device_authorization.py +++ b/appwrite/models/oauth2_device_authorization.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -30,3 +30,24 @@ class Oauth2DeviceAuthorization(AppwriteModel): verification_uri_complete: str = Field(..., alias='verification_uri_complete') expires_in: float = Field(..., alias='expires_in') interval: float = Field(..., alias='interval') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'device_code' not in data: + data['device_code'] = '' + if 'user_code' not in data: + data['user_code'] = '' + if 'verification_uri' not in data: + data['verification_uri'] = '' + if 'verification_uri_complete' not in data: + data['verification_uri_complete'] = '' + if 'expires_in' not in data: + data['expires_in'] = 0 + if 'interval' not in data: + data['interval'] = 0 + return data diff --git a/appwrite/models/oauth2_grant.py b/appwrite/models/oauth2_grant.py index ffa000d9..1ff0a4a1 100644 --- a/appwrite/models/oauth2_grant.py +++ b/appwrite/models/oauth2_grant.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -48,3 +48,36 @@ class Oauth2Grant(AppwriteModel): redirecturi: str = Field(..., alias='redirectUri') authtime: float = Field(..., alias='authTime') expire: str = Field(..., alias='expire') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'appId' not in data and 'appid' not in data: + data['appId'] = '' + if 'scopes' not in data: + data['scopes'] = [] + if 'resources' not in data: + data['resources'] = [] + if 'authorizationDetails' not in data and 'authorizationdetails' not in data: + data['authorizationDetails'] = '[]' + if 'prompt' not in data: + data['prompt'] = '' + if 'redirectUri' not in data and 'redirecturi' not in data: + data['redirectUri'] = '' + if 'authTime' not in data and 'authtime' not in data: + data['authTime'] = 0 + if 'expire' not in data: + data['expire'] = '' + return data diff --git a/appwrite/models/oauth2_introspection.py b/appwrite/models/oauth2_introspection.py index 9fa80c5e..8e176511 100644 --- a/appwrite/models/oauth2_introspection.py +++ b/appwrite/models/oauth2_introspection.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -48,3 +48,14 @@ class Oauth2Introspection(AppwriteModel): iat: Optional[float] = Field(default=None, alias='iat') jti: Optional[str] = Field(default=None, alias='jti') authorization_details: Optional[List[Any]] = Field(default=None, alias='authorization_details') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'active' not in data: + data['active'] = False + return data diff --git a/appwrite/models/oauth2_organization.py b/appwrite/models/oauth2_organization.py index 4df5b972..72f5f02d 100644 --- a/appwrite/models/oauth2_organization.py +++ b/appwrite/models/oauth2_organization.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -15,3 +15,14 @@ class Oauth2Organization(AppwriteModel): """ id: str = Field(..., alias='$id') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + return data diff --git a/appwrite/models/oauth2_organization_list.py b/appwrite/models/oauth2_organization_list.py index b1dbba39..8232ed69 100644 --- a/appwrite/models/oauth2_organization_list.py +++ b/appwrite/models/oauth2_organization_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .oauth2_organization import Oauth2Organization @@ -19,3 +19,16 @@ class Oauth2OrganizationList(AppwriteModel): total: float = Field(..., alias='total') organizations: List[Oauth2Organization] = Field(..., alias='organizations') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'organizations' not in data: + data['organizations'] = [] + return data diff --git a/appwrite/models/oauth2_par.py b/appwrite/models/oauth2_par.py index 49d8b20b..e1b70686 100644 --- a/appwrite/models/oauth2_par.py +++ b/appwrite/models/oauth2_par.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class Oauth2PAR(AppwriteModel): request_uri: str = Field(..., alias='request_uri') expires_in: float = Field(..., alias='expires_in') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'request_uri' not in data: + data['request_uri'] = '' + if 'expires_in' not in data: + data['expires_in'] = 0 + return data diff --git a/appwrite/models/oauth2_project.py b/appwrite/models/oauth2_project.py index 0c06806a..a290119a 100644 --- a/appwrite/models/oauth2_project.py +++ b/appwrite/models/oauth2_project.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -21,3 +21,18 @@ class Oauth2Project(AppwriteModel): id: str = Field(..., alias='$id') region: str = Field(..., alias='region') endpoint: str = Field(..., alias='endpoint') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'region' not in data: + data['region'] = '' + if 'endpoint' not in data: + data['endpoint'] = '' + return data diff --git a/appwrite/models/oauth2_project_list.py b/appwrite/models/oauth2_project_list.py index 03864e13..b1598db2 100644 --- a/appwrite/models/oauth2_project_list.py +++ b/appwrite/models/oauth2_project_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .oauth2_project import Oauth2Project @@ -19,3 +19,16 @@ class Oauth2ProjectList(AppwriteModel): total: float = Field(..., alias='total') projects: List[Oauth2Project] = Field(..., alias='projects') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'projects' not in data: + data['projects'] = [] + return data diff --git a/appwrite/models/oauth2_reject.py b/appwrite/models/oauth2_reject.py index 148df6df..d2e8270a 100644 --- a/appwrite/models/oauth2_reject.py +++ b/appwrite/models/oauth2_reject.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -15,3 +15,14 @@ class Oauth2Reject(AppwriteModel): """ redirecturl: str = Field(..., alias='redirectUrl') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'redirectUrl' not in data and 'redirecturl' not in data: + data['redirectUrl'] = '' + return data diff --git a/appwrite/models/oauth2_token.py b/appwrite/models/oauth2_token.py index 81f7e851..f57d8995 100644 --- a/appwrite/models/oauth2_token.py +++ b/appwrite/models/oauth2_token.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -33,3 +33,22 @@ class Oauth2Token(AppwriteModel): scope: str = Field(..., alias='scope') authorization_details: Optional[str] = Field(default=None, alias='authorization_details') id_token: Optional[str] = Field(default=None, alias='id_token') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'access_token' not in data: + data['access_token'] = '' + if 'token_type' not in data: + data['token_type'] = 'Bearer' + if 'expires_in' not in data: + data['expires_in'] = 0 + if 'refresh_token' not in data: + data['refresh_token'] = '' + if 'scope' not in data: + data['scope'] = '' + return data diff --git a/appwrite/models/organization.py b/appwrite/models/organization.py index cb1a59b6..b70f83f2 100644 --- a/appwrite/models/organization.py +++ b/appwrite/models/organization.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast, Generic, TypeVar, Type -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .preferences import Preferences @@ -39,21 +39,21 @@ class Organization(AppwriteModel, Generic[T]): Organization's billing plan. billingemail : str Billing email set for the organization. - billingstartdate : str + billingstartdate : Optional[str] Billing cycle start date. - billingcurrentinvoicedate : str + billingcurrentinvoicedate : Optional[str] Current invoice cycle start date. - billingnextinvoicedate : str + billingnextinvoicedate : Optional[str] Next invoice cycle start date. billingtrialstartdate : Optional[str] Start date of trial. - billingtrialdays : float + billingtrialdays : Optional[float] Number of trial days. - billingaggregationid : str + billingaggregationid : Optional[str] Current active aggregation id. - billinginvoiceid : str + billinginvoiceid : Optional[str] Current active aggregation id. - paymentmethodid : str + paymentmethodid : Optional[str] Default payment method. billingaddressid : Optional[str] Default payment method. @@ -99,14 +99,14 @@ class Organization(AppwriteModel, Generic[T]): billingplanid: str = Field(..., alias='billingPlanId') billingplandetails: BillingPlan = Field(..., alias='billingPlanDetails') billingemail: str = Field(..., alias='billingEmail') - billingstartdate: str = Field(..., alias='billingStartDate') - billingcurrentinvoicedate: str = Field(..., alias='billingCurrentInvoiceDate') - billingnextinvoicedate: str = Field(..., alias='billingNextInvoiceDate') + billingstartdate: Optional[str] = Field(default=None, alias='billingStartDate') + billingcurrentinvoicedate: Optional[str] = Field(default=None, alias='billingCurrentInvoiceDate') + billingnextinvoicedate: Optional[str] = Field(default=None, alias='billingNextInvoiceDate') billingtrialstartdate: Optional[str] = Field(default=None, alias='billingTrialStartDate') - billingtrialdays: float = Field(..., alias='billingTrialDays') - billingaggregationid: str = Field(..., alias='billingAggregationId') - billinginvoiceid: str = Field(..., alias='billingInvoiceId') - paymentmethodid: str = Field(..., alias='paymentMethodId') + billingtrialdays: Optional[float] = Field(default=None, alias='billingTrialDays') + billingaggregationid: Optional[str] = Field(default=None, alias='billingAggregationId') + billinginvoiceid: Optional[str] = Field(default=None, alias='billingInvoiceId') + paymentmethodid: Optional[str] = Field(default=None, alias='paymentMethodId') billingaddressid: Optional[str] = Field(default=None, alias='billingAddressId') backuppaymentmethodid: Optional[str] = Field(default=None, alias='backupPaymentMethodId') status: str = Field(..., alias='status') @@ -123,6 +123,41 @@ class Organization(AppwriteModel, Generic[T]): platform: str = Field(..., alias='platform') projects: List[Any] = Field(..., alias='projects') + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'total' not in data: + data['total'] = 0 + if 'budgetAlerts' not in data and 'budgetalerts' not in data: + data['budgetAlerts'] = [75] + if 'billingPlan' not in data and 'billingplan' not in data: + data['billingPlan'] = 'tier-0' + if 'billingPlanId' not in data and 'billingplanid' not in data: + data['billingPlanId'] = 'tier-0' + if 'billingEmail' not in data and 'billingemail' not in data: + data['billingEmail'] = '' + if 'status' not in data: + data['status'] = 'draft' + if 'markedForDeletion' not in data and 'markedfordeletion' not in data: + data['markedForDeletion'] = False + if 'platform' not in data: + data['platform'] = 'appwrite' + if 'projects' not in data: + data['projects'] = [] + return data + @classmethod def with_data(cls, data: Dict[str, Any], model_type: Type[T] = dict) -> 'Organization[T]': """Create Organization instance with typed data.""" diff --git a/appwrite/models/passkey.py b/appwrite/models/passkey.py index 556095ab..a35e5235 100644 --- a/appwrite/models/passkey.py +++ b/appwrite/models/passkey.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,22 @@ class Passkey(AppwriteModel): updatedat: str = Field(..., alias='$updatedAt') name: str = Field(..., alias='name') accessedat: str = Field(..., alias='accessedAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'accessedAt' not in data and 'accessedat' not in data: + data['accessedAt'] = '' + return data diff --git a/appwrite/models/passkey_challenge.py b/appwrite/models/passkey_challenge.py index 6f40851d..cbbba256 100644 --- a/appwrite/models/passkey_challenge.py +++ b/appwrite/models/passkey_challenge.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,22 @@ class PasskeyChallenge(AppwriteModel): passkeyid: str = Field(..., alias='passkeyId') expire: str = Field(..., alias='expire') publickey: Dict[str, Any] = Field(..., alias='publicKey') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if 'passkeyId' not in data and 'passkeyid' not in data: + data['passkeyId'] = '' + if 'expire' not in data: + data['expire'] = '' + if 'publicKey' not in data and 'publickey' not in data: + data['publicKey'] = {} + return data diff --git a/appwrite/models/passkey_list.py b/appwrite/models/passkey_list.py index b492b3f2..f1e58280 100644 --- a/appwrite/models/passkey_list.py +++ b/appwrite/models/passkey_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .passkey import Passkey @@ -19,3 +19,16 @@ class PasskeyList(AppwriteModel): total: float = Field(..., alias='total') passkeys: List[Passkey] = Field(..., alias='passkeys') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'passkeys' not in data: + data['passkeys'] = [] + return data diff --git a/appwrite/models/phone.py b/appwrite/models/phone.py index 9df4f3e2..19a8b06a 100644 --- a/appwrite/models/phone.py +++ b/appwrite/models/phone.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -21,3 +21,18 @@ class Phone(AppwriteModel): code: str = Field(..., alias='code') countrycode: str = Field(..., alias='countryCode') countryname: str = Field(..., alias='countryName') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'code' not in data: + data['code'] = '' + if 'countryCode' not in data and 'countrycode' not in data: + data['countryCode'] = '' + if 'countryName' not in data and 'countryname' not in data: + data['countryName'] = '' + return data diff --git a/appwrite/models/phone_list.py b/appwrite/models/phone_list.py index e9cc2679..c72aa3e4 100644 --- a/appwrite/models/phone_list.py +++ b/appwrite/models/phone_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .phone import Phone @@ -19,3 +19,16 @@ class PhoneList(AppwriteModel): total: float = Field(..., alias='total') phones: List[Phone] = Field(..., alias='phones') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'phones' not in data: + data['phones'] = [] + return data diff --git a/appwrite/models/platform_android.py b/appwrite/models/platform_android.py index 066c215e..c2de838e 100644 --- a/appwrite/models/platform_android.py +++ b/appwrite/models/platform_android.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.platform_type import PlatformType @@ -23,7 +23,7 @@ class PlatformAndroid(AppwriteModel): Platform type. Possible values are: windows, apple, android, linux, web. applicationid : str Android application ID. - fingerprints : Optional[List[Any]] + fingerprints : List[Any] SHA-256 fingerprints of the certificates the app is signed with. Passkeys created in the app are accepted when its signature matches one. """ @@ -33,4 +33,25 @@ class PlatformAndroid(AppwriteModel): name: str = Field(..., alias='name') type: PlatformType = Field(..., alias='type') applicationid: str = Field(..., alias='applicationId') - fingerprints: Optional[List[Any]] = Field(default=None, alias='fingerprints') + fingerprints: List[Any] = Field(..., alias='fingerprints') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'applicationId' not in data and 'applicationid' not in data: + data['applicationId'] = '' + if 'fingerprints' not in data: + data['fingerprints'] = [] + return data diff --git a/appwrite/models/platform_apple.py b/appwrite/models/platform_apple.py index 1d1cb315..627c6aab 100644 --- a/appwrite/models/platform_apple.py +++ b/appwrite/models/platform_apple.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.platform_type import PlatformType @@ -31,3 +31,22 @@ class PlatformApple(AppwriteModel): name: str = Field(..., alias='name') type: PlatformType = Field(..., alias='type') bundleidentifier: str = Field(..., alias='bundleIdentifier') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'bundleIdentifier' not in data and 'bundleidentifier' not in data: + data['bundleIdentifier'] = '' + return data diff --git a/appwrite/models/platform_linux.py b/appwrite/models/platform_linux.py index 82958e80..01ea9b78 100644 --- a/appwrite/models/platform_linux.py +++ b/appwrite/models/platform_linux.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.platform_type import PlatformType @@ -31,3 +31,22 @@ class PlatformLinux(AppwriteModel): name: str = Field(..., alias='name') type: PlatformType = Field(..., alias='type') packagename: str = Field(..., alias='packageName') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'packageName' not in data and 'packagename' not in data: + data['packageName'] = '' + return data diff --git a/appwrite/models/platform_list.py b/appwrite/models/platform_list.py index eb30c63f..297aee36 100644 --- a/appwrite/models/platform_list.py +++ b/appwrite/models/platform_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .platform_web import PlatformWeb @@ -31,3 +31,16 @@ class PlatformList(AppwriteModel): PlatformLinux, ] ] = Field(..., alias='platforms') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'platforms' not in data: + data['platforms'] = [] + return data diff --git a/appwrite/models/platform_web.py b/appwrite/models/platform_web.py index 4e69b96f..9c40ebd4 100644 --- a/appwrite/models/platform_web.py +++ b/appwrite/models/platform_web.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.platform_type import PlatformType @@ -31,3 +31,22 @@ class PlatformWeb(AppwriteModel): name: str = Field(..., alias='name') type: PlatformType = Field(..., alias='type') hostname: str = Field(..., alias='hostname') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'hostname' not in data: + data['hostname'] = '' + return data diff --git a/appwrite/models/platform_windows.py b/appwrite/models/platform_windows.py index fdabffb2..915877b8 100644 --- a/appwrite/models/platform_windows.py +++ b/appwrite/models/platform_windows.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.platform_type import PlatformType @@ -31,3 +31,22 @@ class PlatformWindows(AppwriteModel): name: str = Field(..., alias='name') type: PlatformType = Field(..., alias='type') packageidentifiername: str = Field(..., alias='packageIdentifierName') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'packageIdentifierName' not in data and 'packageidentifiername' not in data: + data['packageIdentifierName'] = '' + return data diff --git a/appwrite/models/policy_deny_aliased_email.py b/appwrite/models/policy_deny_aliased_email.py index 64e65644..fe78898e 100644 --- a/appwrite/models/policy_deny_aliased_email.py +++ b/appwrite/models/policy_deny_aliased_email.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class PolicyDenyAliasedEmail(AppwriteModel): id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + return data diff --git a/appwrite/models/policy_deny_corporate_email.py b/appwrite/models/policy_deny_corporate_email.py index b56e12fb..d6e6b5f5 100644 --- a/appwrite/models/policy_deny_corporate_email.py +++ b/appwrite/models/policy_deny_corporate_email.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class PolicyDenyCorporateEmail(AppwriteModel): id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + return data diff --git a/appwrite/models/policy_deny_disposable_email.py b/appwrite/models/policy_deny_disposable_email.py index 4f571733..481923ec 100644 --- a/appwrite/models/policy_deny_disposable_email.py +++ b/appwrite/models/policy_deny_disposable_email.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class PolicyDenyDisposableEmail(AppwriteModel): id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + return data diff --git a/appwrite/models/policy_deny_free_email.py b/appwrite/models/policy_deny_free_email.py index 1eb610ee..122cec77 100644 --- a/appwrite/models/policy_deny_free_email.py +++ b/appwrite/models/policy_deny_free_email.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class PolicyDenyFreeEmail(AppwriteModel): id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + return data diff --git a/appwrite/models/policy_list.py b/appwrite/models/policy_list.py index c2938e49..af4063f2 100644 --- a/appwrite/models/policy_list.py +++ b/appwrite/models/policy_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .policy_password_dictionary import PolicyPasswordDictionary @@ -57,3 +57,16 @@ class PolicyList(AppwriteModel): PolicyPasskey, ] ] = Field(..., alias='policies') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'policies' not in data: + data['policies'] = [] + return data diff --git a/appwrite/models/policy_membership_privacy.py b/appwrite/models/policy_membership_privacy.py index 157913ac..bbc215ff 100644 --- a/appwrite/models/policy_membership_privacy.py +++ b/appwrite/models/policy_membership_privacy.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -33,3 +33,26 @@ class PolicyMembershipPrivacy(AppwriteModel): username: bool = Field(..., alias='userName') usermfa: bool = Field(..., alias='userMFA') useraccessedat: bool = Field(..., alias='userAccessedAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = False + if 'userEmail' not in data and 'useremail' not in data: + data['userEmail'] = False + if 'userPhone' not in data and 'userphone' not in data: + data['userPhone'] = False + if 'userName' not in data and 'username' not in data: + data['userName'] = False + if 'userMFA' not in data and 'usermfa' not in data: + data['userMFA'] = False + if 'userAccessedAt' not in data and 'useraccessedat' not in data: + data['userAccessedAt'] = False + return data diff --git a/appwrite/models/policy_mfa_factors.py b/appwrite/models/policy_mfa_factors.py index 12b5b20b..202891e8 100644 --- a/appwrite/models/policy_mfa_factors.py +++ b/appwrite/models/policy_mfa_factors.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,3 +27,22 @@ class PolicyMfaFactors(AppwriteModel): email: bool = Field(..., alias='email') phone: bool = Field(..., alias='phone') custom: bool = Field(..., alias='custom') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'totp' not in data: + data['totp'] = True + if 'email' not in data: + data['email'] = True + if 'phone' not in data: + data['phone'] = True + if 'custom' not in data: + data['custom'] = False + return data diff --git a/appwrite/models/policy_passkey.py b/appwrite/models/policy_passkey.py index 7ec34d7a..488e5f5b 100644 --- a/appwrite/models/policy_passkey.py +++ b/appwrite/models/policy_passkey.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -21,3 +21,18 @@ class PolicyPasskey(AppwriteModel): id: str = Field(..., alias='$id') rpid: str = Field(..., alias='rpId') origins: List[Any] = Field(..., alias='origins') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'rpId' not in data and 'rpid' not in data: + data['rpId'] = '' + if 'origins' not in data: + data['origins'] = [] + return data diff --git a/appwrite/models/policy_password_dictionary.py b/appwrite/models/policy_password_dictionary.py index e5046106..37bbbeeb 100644 --- a/appwrite/models/policy_password_dictionary.py +++ b/appwrite/models/policy_password_dictionary.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class PolicyPasswordDictionary(AppwriteModel): id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + return data diff --git a/appwrite/models/policy_password_history.py b/appwrite/models/policy_password_history.py index f8eff9a7..26e50c4d 100644 --- a/appwrite/models/policy_password_history.py +++ b/appwrite/models/policy_password_history.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class PolicyPasswordHistory(AppwriteModel): id: str = Field(..., alias='$id') total: float = Field(..., alias='total') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'total' not in data: + data['total'] = 0 + return data diff --git a/appwrite/models/policy_password_personal_data.py b/appwrite/models/policy_password_personal_data.py index 92710579..64f12c7c 100644 --- a/appwrite/models/policy_password_personal_data.py +++ b/appwrite/models/policy_password_personal_data.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class PolicyPasswordPersonalData(AppwriteModel): id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + return data diff --git a/appwrite/models/policy_password_pwned.py b/appwrite/models/policy_password_pwned.py index 90c58d38..06d4a1bc 100644 --- a/appwrite/models/policy_password_pwned.py +++ b/appwrite/models/policy_password_pwned.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class PolicyPasswordPwned(AppwriteModel): enabled: bool = Field(..., alias='enabled') sessions: bool = Field(..., alias='sessions') users: bool = Field(..., alias='users') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = True + if 'sessions' not in data: + data['sessions'] = False + if 'users' not in data: + data['users'] = False + return data diff --git a/appwrite/models/policy_password_rotation.py b/appwrite/models/policy_password_rotation.py index 080071f5..118fffc0 100644 --- a/appwrite/models/policy_password_rotation.py +++ b/appwrite/models/policy_password_rotation.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -21,3 +21,18 @@ class PolicyPasswordRotation(AppwriteModel): id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') maxage: float = Field(..., alias='maxAge') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + if 'maxAge' not in data and 'maxage' not in data: + data['maxAge'] = 31536000 + return data diff --git a/appwrite/models/policy_password_strength.py b/appwrite/models/policy_password_strength.py index db9b6bc6..3a01bca2 100644 --- a/appwrite/models/policy_password_strength.py +++ b/appwrite/models/policy_password_strength.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -30,3 +30,24 @@ class PolicyPasswordStrength(AppwriteModel): lowercase: bool = Field(..., alias='lowercase') number: bool = Field(..., alias='number') symbols: bool = Field(..., alias='symbols') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'min' not in data: + data['min'] = 8 + if 'uppercase' not in data: + data['uppercase'] = False + if 'lowercase' not in data: + data['lowercase'] = False + if 'number' not in data: + data['number'] = False + if 'symbols' not in data: + data['symbols'] = False + return data diff --git a/appwrite/models/policy_session_alert.py b/appwrite/models/policy_session_alert.py index f8f87a4d..90c62081 100644 --- a/appwrite/models/policy_session_alert.py +++ b/appwrite/models/policy_session_alert.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class PolicySessionAlert(AppwriteModel): id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = False + return data diff --git a/appwrite/models/policy_session_duration.py b/appwrite/models/policy_session_duration.py index 7b688476..49a362bf 100644 --- a/appwrite/models/policy_session_duration.py +++ b/appwrite/models/policy_session_duration.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class PolicySessionDuration(AppwriteModel): id: str = Field(..., alias='$id') duration: float = Field(..., alias='duration') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'duration' not in data: + data['duration'] = 31536000 + return data diff --git a/appwrite/models/policy_session_invalidation.py b/appwrite/models/policy_session_invalidation.py index ffce62db..6c71d822 100644 --- a/appwrite/models/policy_session_invalidation.py +++ b/appwrite/models/policy_session_invalidation.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class PolicySessionInvalidation(AppwriteModel): id: str = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'enabled' not in data: + data['enabled'] = True + return data diff --git a/appwrite/models/policy_session_limit.py b/appwrite/models/policy_session_limit.py index 36590466..18eca7ce 100644 --- a/appwrite/models/policy_session_limit.py +++ b/appwrite/models/policy_session_limit.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class PolicySessionLimit(AppwriteModel): id: str = Field(..., alias='$id') total: float = Field(..., alias='total') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'total' not in data: + data['total'] = 0 + return data diff --git a/appwrite/models/policy_user_limit.py b/appwrite/models/policy_user_limit.py index 485879fd..d3757ff4 100644 --- a/appwrite/models/policy_user_limit.py +++ b/appwrite/models/policy_user_limit.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -18,3 +18,16 @@ class PolicyUserLimit(AppwriteModel): id: str = Field(..., alias='$id') total: float = Field(..., alias='total') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'total' not in data: + data['total'] = 0 + return data diff --git a/appwrite/models/postgres_extension.py b/appwrite/models/postgres_extension.py index 9f8cfdc7..5c1ab950 100644 --- a/appwrite/models/postgres_extension.py +++ b/appwrite/models/postgres_extension.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class PostgresExtension(AppwriteModel): name: str = Field(..., alias='name') description: str = Field(..., alias='description') category: str = Field(..., alias='category') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'key' not in data: + data['key'] = '' + if 'name' not in data: + data['name'] = '' + if 'description' not in data: + data['description'] = '' + if 'category' not in data: + data['category'] = '' + return data diff --git a/appwrite/models/presence.py b/appwrite/models/presence.py index 79556f7a..d78dbf55 100644 --- a/appwrite/models/presence.py +++ b/appwrite/models/presence.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -39,3 +39,24 @@ class Presence(AppwriteModel): source: str = Field(..., alias='source') expiresat: Optional[str] = Field(default=None, alias='expiresAt') metadata: Optional[Dict[str, Any]] = Field(default=None, alias='metadata') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if '$permissions' not in data and 'permissions' not in data: + data['$permissions'] = [] + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'source' not in data: + data['source'] = '' + return data diff --git a/appwrite/models/presence_list.py b/appwrite/models/presence_list.py index 1d8752a6..71c082de 100644 --- a/appwrite/models/presence_list.py +++ b/appwrite/models/presence_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .presence import Presence @@ -19,3 +19,16 @@ class PresenceList(AppwriteModel): total: float = Field(..., alias='total') presences: List[Presence] = Field(..., alias='presences') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'presences' not in data: + data['presences'] = [] + return data diff --git a/appwrite/models/program.py b/appwrite/models/program.py index e2f5b081..204b91a9 100644 --- a/appwrite/models/program.py +++ b/appwrite/models/program.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -39,3 +39,30 @@ class Program(AppwriteModel): active: bool = Field(..., alias='active') external: bool = Field(..., alias='external') billingplanid: str = Field(..., alias='billingPlanId') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'title' not in data: + data['title'] = '' + if 'description' not in data: + data['description'] = '' + if 'tag' not in data: + data['tag'] = '' + if 'icon' not in data: + data['icon'] = '' + if 'url' not in data: + data['url'] = '' + if 'active' not in data: + data['active'] = True + if 'external' not in data: + data['external'] = True + if 'billingPlanId' not in data and 'billingplanid' not in data: + data['billingPlanId'] = '' + return data diff --git a/appwrite/models/project.py b/appwrite/models/project.py index 6b12b5ff..f1420ab2 100644 --- a/appwrite/models/project.py +++ b/appwrite/models/project.py @@ -1,8 +1,7 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel -from .dev_key import DevKey from .project_auth_method import ProjectAuthMethod from .project_service import ProjectService from .project_protocol import ProjectProtocol @@ -28,8 +27,6 @@ class Project(AppwriteModel): Project team ID. region : str Project region - devkeys : List[DevKey] - Deprecated since 1.9.5: List of dev keys. smtpenabled : bool Status for custom SMTP smtpsendername : str @@ -122,7 +119,6 @@ class Project(AppwriteModel): name: str = Field(..., alias='name') teamid: str = Field(..., alias='teamId') region: str = Field(..., alias='region') - devkeys: List[DevKey] = Field(..., alias='devKeys') smtpenabled: bool = Field(..., alias='smtpEnabled') smtpsendername: str = Field(..., alias='smtpSenderName') smtpsenderemail: str = Field(..., alias='smtpSenderEmail') @@ -177,3 +173,64 @@ class Project(AppwriteModel): oauth2serverusercodeformat: Optional[str] = Field(default=None, alias='oAuth2ServerUserCodeFormat') oauth2serverdevicecodeduration: Optional[float] = Field(default=None, alias='oAuth2ServerDeviceCodeDuration') oauth2serverdiscoveryurl: Optional[str] = Field(default=None, alias='oAuth2ServerDiscoveryUrl') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'teamId' not in data and 'teamid' not in data: + data['teamId'] = '' + if 'region' not in data: + data['region'] = 'fra' + if 'smtpEnabled' not in data and 'smtpenabled' not in data: + data['smtpEnabled'] = False + if 'smtpSenderName' not in data and 'smtpsendername' not in data: + data['smtpSenderName'] = '' + if 'smtpSenderEmail' not in data and 'smtpsenderemail' not in data: + data['smtpSenderEmail'] = '' + if 'smtpReplyToName' not in data and 'smtpreplytoname' not in data: + data['smtpReplyToName'] = '' + if 'smtpReplyToEmail' not in data and 'smtpreplytoemail' not in data: + data['smtpReplyToEmail'] = '' + if 'smtpHost' not in data and 'smtphost' not in data: + data['smtpHost'] = '' + if 'smtpPort' not in data and 'smtpport' not in data: + data['smtpPort'] = 0 + if 'smtpUsername' not in data and 'smtpusername' not in data: + data['smtpUsername'] = '' + if 'smtpPassword' not in data and 'smtppassword' not in data: + data['smtpPassword'] = '' + if 'smtpSecure' not in data and 'smtpsecure' not in data: + data['smtpSecure'] = '' + if 'pingCount' not in data and 'pingcount' not in data: + data['pingCount'] = 0 + if 'pingedAt' not in data and 'pingedat' not in data: + data['pingedAt'] = '' + if 'labels' not in data: + data['labels'] = [] + if 'status' not in data: + data['status'] = 'active' + if 'onboarding' not in data: + data['onboarding'] = {} + if 'authMethods' not in data and 'authmethods' not in data: + data['authMethods'] = [] + if 'services' not in data: + data['services'] = [] + if 'protocols' not in data: + data['protocols'] = [] + if 'blocks' not in data: + data['blocks'] = [] + if 'consoleAccessedAt' not in data and 'consoleaccessedat' not in data: + data['consoleAccessedAt'] = '' + return data diff --git a/appwrite/models/project_auth_method.py b/appwrite/models/project_auth_method.py index 76df540b..14df4090 100644 --- a/appwrite/models/project_auth_method.py +++ b/appwrite/models/project_auth_method.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.project_auth_method_id import ProjectAuthMethodId @@ -19,3 +19,14 @@ class ProjectAuthMethod(AppwriteModel): id: ProjectAuthMethodId = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'enabled' not in data: + data['enabled'] = True + return data diff --git a/appwrite/models/project_list.py b/appwrite/models/project_list.py index 31cc5425..8e305afc 100644 --- a/appwrite/models/project_list.py +++ b/appwrite/models/project_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .project import Project @@ -19,3 +19,16 @@ class ProjectList(AppwriteModel): total: float = Field(..., alias='total') projects: List[Project] = Field(..., alias='projects') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'projects' not in data: + data['projects'] = [] + return data diff --git a/appwrite/models/project_protocol.py b/appwrite/models/project_protocol.py index 8be9c7e7..202b8668 100644 --- a/appwrite/models/project_protocol.py +++ b/appwrite/models/project_protocol.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.project_protocol_id import ProjectProtocolId @@ -19,3 +19,14 @@ class ProjectProtocol(AppwriteModel): id: ProjectProtocolId = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'enabled' not in data: + data['enabled'] = True + return data diff --git a/appwrite/models/project_service.py b/appwrite/models/project_service.py index da1d0df4..05ab6bee 100644 --- a/appwrite/models/project_service.py +++ b/appwrite/models/project_service.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.project_service_id import ProjectServiceId @@ -19,3 +19,14 @@ class ProjectService(AppwriteModel): id: ProjectServiceId = Field(..., alias='$id') enabled: bool = Field(..., alias='enabled') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'enabled' not in data: + data['enabled'] = True + return data diff --git a/appwrite/models/provider.py b/appwrite/models/provider.py index b08954cd..ebe30dfb 100644 --- a/appwrite/models/provider.py +++ b/appwrite/models/provider.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -39,3 +39,28 @@ class Provider(AppwriteModel): type: str = Field(..., alias='type') credentials: Dict[str, Any] = Field(..., alias='credentials') options: Optional[Dict[str, Any]] = Field(default=None, alias='options') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'provider' not in data: + data['provider'] = '' + if 'enabled' not in data: + data['enabled'] = True + if 'type' not in data: + data['type'] = '' + if 'credentials' not in data: + data['credentials'] = {} + return data diff --git a/appwrite/models/provider_list.py b/appwrite/models/provider_list.py index c6265653..fe0544b3 100644 --- a/appwrite/models/provider_list.py +++ b/appwrite/models/provider_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .provider import Provider @@ -19,3 +19,16 @@ class ProviderList(AppwriteModel): total: float = Field(..., alias='total') providers: List[Provider] = Field(..., alias='providers') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'providers' not in data: + data['providers'] = [] + return data diff --git a/appwrite/models/proxy_invalidation.py b/appwrite/models/proxy_invalidation.py index 586ba9e3..b0e08da9 100644 --- a/appwrite/models/proxy_invalidation.py +++ b/appwrite/models/proxy_invalidation.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class ProxyInvalidation(AppwriteModel): type: str = Field(..., alias='type') reference: str = Field(..., alias='reference') status: str = Field(..., alias='status') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'domain' not in data: + data['domain'] = '' + if 'type' not in data: + data['type'] = '' + if 'reference' not in data: + data['reference'] = '' + if 'status' not in data: + data['status'] = '' + return data diff --git a/appwrite/models/proxy_rule.py b/appwrite/models/proxy_rule.py index 53a3d0d8..0fdac26a 100644 --- a/appwrite/models/proxy_rule.py +++ b/appwrite/models/proxy_rule.py @@ -1,9 +1,10 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.proxy_rule_deployment_resource_type import ProxyRuleDeploymentResourceType from ..enums.proxy_rule_status import ProxyRuleStatus +from ..enums.proxy_rule_protocol import ProxyRuleProtocol class ProxyRule(AppwriteModel): @@ -31,7 +32,7 @@ class ProxyRule(AppwriteModel): deploymentid : str ID of deployment. Used if type is "deployment" deploymentresourcetype : Optional[ProxyRuleDeploymentResourceType] - Type of deployment. Possible values are "function", "site". Used if rule's type is "deployment". + Type of deployment resource: function, site, or dedicatedDatabase. deploymentresourceid : str ID of deployment's resource (site or function ID). Used if type is "deployment" deploymentvcsproviderbranch : str @@ -42,6 +43,8 @@ class ProxyRule(AppwriteModel): Logs from rule verification or certificate generation. Certificate generation logs are prioritized if both are available. renewat : str Certificate auto-renewal date in ISO 8601 format. + protocol : ProxyRuleProtocol + Ingress protocol for the rule. """ id: str = Field(..., alias='$id') @@ -62,3 +65,41 @@ class ProxyRule(AppwriteModel): status: ProxyRuleStatus = Field(..., alias='status') logs: str = Field(..., alias='logs') renewat: str = Field(..., alias='renewAt') + protocol: ProxyRuleProtocol = Field(..., alias='protocol') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'domain' not in data: + data['domain'] = '' + if 'type' not in data: + data['type'] = '' + if 'trigger' not in data: + data['trigger'] = '' + if 'redirectUrl' not in data and 'redirecturl' not in data: + data['redirectUrl'] = '' + if 'redirectStatusCode' not in data and 'redirectstatuscode' not in data: + data['redirectStatusCode'] = 301 + if 'deploymentId' not in data and 'deploymentid' not in data: + data['deploymentId'] = '' + if 'deploymentResourceId' not in data and 'deploymentresourceid' not in data: + data['deploymentResourceId'] = '' + if 'deploymentVcsProviderBranch' not in data and 'deploymentvcsproviderbranch' not in data: + data['deploymentVcsProviderBranch'] = '' + if 'status' not in data: + data['status'] = 'unverified' + if 'logs' not in data: + data['logs'] = '' + if 'protocol' not in data: + data['protocol'] = 'http' + return data diff --git a/appwrite/models/proxy_rule_list.py b/appwrite/models/proxy_rule_list.py index 8c266224..dbcae930 100644 --- a/appwrite/models/proxy_rule_list.py +++ b/appwrite/models/proxy_rule_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .proxy_rule import ProxyRule @@ -19,3 +19,16 @@ class ProxyRuleList(AppwriteModel): total: float = Field(..., alias='total') rules: List[ProxyRule] = Field(..., alias='rules') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'rules' not in data: + data['rules'] = [] + return data diff --git a/appwrite/models/report.py b/appwrite/models/report.py index 88241b4f..dfcb3ef2 100644 --- a/appwrite/models/report.py +++ b/appwrite/models/report.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .insight import Insight @@ -49,3 +49,34 @@ class Report(AppwriteModel): categories: List[Any] = Field(..., alias='categories') insights: List[Insight] = Field(..., alias='insights') analyzedat: Optional[str] = Field(default=None, alias='analyzedAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'appId' not in data and 'appid' not in data: + data['appId'] = '' + if 'type' not in data: + data['type'] = '' + if 'title' not in data: + data['title'] = '' + if 'summary' not in data: + data['summary'] = '' + if 'targetType' not in data and 'targettype' not in data: + data['targetType'] = '' + if 'target' not in data: + data['target'] = '' + if 'categories' not in data: + data['categories'] = [] + if 'insights' not in data: + data['insights'] = [] + return data diff --git a/appwrite/models/report_list.py b/appwrite/models/report_list.py index 3edfb434..9bc2a418 100644 --- a/appwrite/models/report_list.py +++ b/appwrite/models/report_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .report import Report @@ -19,3 +19,16 @@ class ReportList(AppwriteModel): total: float = Field(..., alias='total') reports: List[Report] = Field(..., alias='reports') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'reports' not in data: + data['reports'] = [] + return data diff --git a/appwrite/models/resource_token.py b/appwrite/models/resource_token.py index c8b9ec05..12fbd31a 100644 --- a/appwrite/models/resource_token.py +++ b/appwrite/models/resource_token.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -33,3 +33,26 @@ class ResourceToken(AppwriteModel): expire: str = Field(..., alias='expire') secret: str = Field(..., alias='secret') accessedat: str = Field(..., alias='accessedAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if 'resourceId' not in data and 'resourceid' not in data: + data['resourceId'] = '' + if 'resourceType' not in data and 'resourcetype' not in data: + data['resourceType'] = '' + if 'expire' not in data: + data['expire'] = '' + if 'secret' not in data: + data['secret'] = '' + if 'accessedAt' not in data and 'accessedat' not in data: + data['accessedAt'] = '' + return data diff --git a/appwrite/models/resource_token_list.py b/appwrite/models/resource_token_list.py index b1ee177e..f149efa3 100644 --- a/appwrite/models/resource_token_list.py +++ b/appwrite/models/resource_token_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .resource_token import ResourceToken @@ -19,3 +19,16 @@ class ResourceTokenList(AppwriteModel): total: float = Field(..., alias='total') tokens: List[ResourceToken] = Field(..., alias='tokens') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'tokens' not in data: + data['tokens'] = [] + return data diff --git a/appwrite/models/row.py b/appwrite/models/row.py index 5a8aa39e..e6d86eab 100644 --- a/appwrite/models/row.py +++ b/appwrite/models/row.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast, Generic, TypeVar, Type -from pydantic import Field, PrivateAttr, TypeAdapter, model_serializer +from pydantic import Field, PrivateAttr, TypeAdapter, model_validator, model_serializer from .base_model import AppwriteModel @@ -38,6 +38,29 @@ class Row(AppwriteModel, Generic[T]): updatedat: str = Field(..., alias='$updatedAt') permissions: List[Any] = Field(..., alias='$permissions') + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$sequence' not in data and 'sequence' not in data: + data['$sequence'] = '' + if '$tableId' not in data and 'tableid' not in data: + data['$tableId'] = '' + if '$databaseId' not in data and 'databaseid' not in data: + data['$databaseId'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if '$permissions' not in data and 'permissions' not in data: + data['$permissions'] = [] + return data + @classmethod def with_data(cls, data: Dict[str, Any], model_type: Type[T] = dict) -> 'Row[T]': """Create Row instance with typed data.""" diff --git a/appwrite/models/row_list.py b/appwrite/models/row_list.py index 174b973d..eb993e54 100644 --- a/appwrite/models/row_list.py +++ b/appwrite/models/row_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast, Generic, TypeVar, Type -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .row import Row @@ -22,6 +22,19 @@ class RowList(AppwriteModel, Generic[T]): total: float = Field(..., alias='total') rows: List[Row[T]] = Field(..., alias='rows') + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'rows' not in data: + data['rows'] = [] + return data + @classmethod def with_data(cls, data: Dict[str, Any], model_type: Type[T] = dict) -> 'RowList[T]': """Create RowList instance with typed data.""" diff --git a/appwrite/models/runtime.py b/appwrite/models/runtime.py index debc5e8a..735161f4 100644 --- a/appwrite/models/runtime.py +++ b/appwrite/models/runtime.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -36,3 +36,28 @@ class Runtime(AppwriteModel): image: str = Field(..., alias='image') logo: str = Field(..., alias='logo') supports: List[Any] = Field(..., alias='supports') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if 'key' not in data: + data['key'] = '' + if 'name' not in data: + data['name'] = '' + if 'version' not in data: + data['version'] = '' + if 'base' not in data: + data['base'] = '' + if 'image' not in data: + data['image'] = '' + if 'logo' not in data: + data['logo'] = '' + if 'supports' not in data: + data['supports'] = [] + return data diff --git a/appwrite/models/runtime_list.py b/appwrite/models/runtime_list.py index 18121a93..001254d1 100644 --- a/appwrite/models/runtime_list.py +++ b/appwrite/models/runtime_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .runtime import Runtime @@ -19,3 +19,16 @@ class RuntimeList(AppwriteModel): total: float = Field(..., alias='total') runtimes: List[Runtime] = Field(..., alias='runtimes') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'runtimes' not in data: + data['runtimes'] = [] + return data diff --git a/appwrite/models/session.py b/appwrite/models/session.py index 01f10bfa..ffcf6b5b 100644 --- a/appwrite/models/session.py +++ b/appwrite/models/session.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -99,3 +99,70 @@ class Session(AppwriteModel): factors: List[Any] = Field(..., alias='factors') secret: str = Field(..., alias='secret') mfaupdatedat: str = Field(..., alias='mfaUpdatedAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'expire' not in data: + data['expire'] = '' + if 'provider' not in data: + data['provider'] = '' + if 'providerUid' not in data and 'provideruid' not in data: + data['providerUid'] = '' + if 'providerAccessToken' not in data and 'provideraccesstoken' not in data: + data['providerAccessToken'] = '' + if 'providerAccessTokenExpiry' not in data and 'provideraccesstokenexpiry' not in data: + data['providerAccessTokenExpiry'] = '' + if 'providerRefreshToken' not in data and 'providerrefreshtoken' not in data: + data['providerRefreshToken'] = '' + if 'ip' not in data: + data['ip'] = '' + if 'osCode' not in data and 'oscode' not in data: + data['osCode'] = '' + if 'osName' not in data and 'osname' not in data: + data['osName'] = '' + if 'osVersion' not in data and 'osversion' not in data: + data['osVersion'] = '' + if 'clientType' not in data and 'clienttype' not in data: + data['clientType'] = '' + if 'clientCode' not in data and 'clientcode' not in data: + data['clientCode'] = '' + if 'clientName' not in data and 'clientname' not in data: + data['clientName'] = '' + if 'clientVersion' not in data and 'clientversion' not in data: + data['clientVersion'] = '' + if 'clientEngine' not in data and 'clientengine' not in data: + data['clientEngine'] = '' + if 'clientEngineVersion' not in data and 'clientengineversion' not in data: + data['clientEngineVersion'] = '' + if 'deviceName' not in data and 'devicename' not in data: + data['deviceName'] = '' + if 'deviceBrand' not in data and 'devicebrand' not in data: + data['deviceBrand'] = '' + if 'deviceModel' not in data and 'devicemodel' not in data: + data['deviceModel'] = '' + if 'countryCode' not in data and 'countrycode' not in data: + data['countryCode'] = '' + if 'countryName' not in data and 'countryname' not in data: + data['countryName'] = '' + if 'current' not in data: + data['current'] = False + if 'factors' not in data: + data['factors'] = [] + if 'secret' not in data: + data['secret'] = '' + if 'mfaUpdatedAt' not in data and 'mfaupdatedat' not in data: + data['mfaUpdatedAt'] = '' + return data diff --git a/appwrite/models/session_list.py b/appwrite/models/session_list.py index 7518f56a..3381a509 100644 --- a/appwrite/models/session_list.py +++ b/appwrite/models/session_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .session import Session @@ -19,3 +19,16 @@ class SessionList(AppwriteModel): total: float = Field(..., alias='total') sessions: List[Session] = Field(..., alias='sessions') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'sessions' not in data: + data['sessions'] = [] + return data diff --git a/appwrite/models/site.py b/appwrite/models/site.py index b6f2aad6..bef638fc 100644 --- a/appwrite/models/site.py +++ b/appwrite/models/site.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .variable import Variable @@ -118,3 +118,78 @@ class Site(AppwriteModel): buildruntime: str = Field(..., alias='buildRuntime') adapter: str = Field(..., alias='adapter') fallbackfile: str = Field(..., alias='fallbackFile') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'enabled' not in data: + data['enabled'] = True + if 'live' not in data: + data['live'] = True + if 'logging' not in data: + data['logging'] = True + if 'framework' not in data: + data['framework'] = '' + if 'deploymentRetention' not in data and 'deploymentretention' not in data: + data['deploymentRetention'] = 0 + if 'deploymentId' not in data and 'deploymentid' not in data: + data['deploymentId'] = '' + if 'deploymentCreatedAt' not in data and 'deploymentcreatedat' not in data: + data['deploymentCreatedAt'] = '' + if 'deploymentScreenshotLight' not in data and 'deploymentscreenshotlight' not in data: + data['deploymentScreenshotLight'] = '' + if 'deploymentScreenshotDark' not in data and 'deploymentscreenshotdark' not in data: + data['deploymentScreenshotDark'] = '' + if 'latestDeploymentId' not in data and 'latestdeploymentid' not in data: + data['latestDeploymentId'] = '' + if 'latestDeploymentCreatedAt' not in data and 'latestdeploymentcreatedat' not in data: + data['latestDeploymentCreatedAt'] = '' + if 'latestDeploymentStatus' not in data and 'latestdeploymentstatus' not in data: + data['latestDeploymentStatus'] = '' + if 'scopes' not in data: + data['scopes'] = [] + if 'vars' not in data: + data['vars'] = [] + if 'timeout' not in data: + data['timeout'] = 15 + if 'installCommand' not in data and 'installcommand' not in data: + data['installCommand'] = '' + if 'buildCommand' not in data and 'buildcommand' not in data: + data['buildCommand'] = '' + if 'startCommand' not in data and 'startcommand' not in data: + data['startCommand'] = '' + if 'outputDirectory' not in data and 'outputdirectory' not in data: + data['outputDirectory'] = '' + if 'installationId' not in data and 'installationid' not in data: + data['installationId'] = '' + if 'providerRepositoryId' not in data and 'providerrepositoryid' not in data: + data['providerRepositoryId'] = '' + if 'providerBranch' not in data and 'providerbranch' not in data: + data['providerBranch'] = '' + if 'providerRootDirectory' not in data and 'providerrootdirectory' not in data: + data['providerRootDirectory'] = '' + if 'providerSilentMode' not in data and 'providersilentmode' not in data: + data['providerSilentMode'] = False + if 'providerBranches' not in data and 'providerbranches' not in data: + data['providerBranches'] = [] + if 'providerPaths' not in data and 'providerpaths' not in data: + data['providerPaths'] = [] + if 'buildSpecification' not in data and 'buildspecification' not in data: + data['buildSpecification'] = 's-1vcpu-512mb' + if 'runtimeSpecification' not in data and 'runtimespecification' not in data: + data['runtimeSpecification'] = 's-1vcpu-512mb' + if 'buildRuntime' not in data and 'buildruntime' not in data: + data['buildRuntime'] = '' + return data diff --git a/appwrite/models/site_list.py b/appwrite/models/site_list.py index cd60234d..69eab0d3 100644 --- a/appwrite/models/site_list.py +++ b/appwrite/models/site_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .site import Site @@ -19,3 +19,16 @@ class SiteList(AppwriteModel): total: float = Field(..., alias='total') sites: List[Site] = Field(..., alias='sites') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'sites' not in data: + data['sites'] = [] + return data diff --git a/appwrite/models/specification.py b/appwrite/models/specification.py index 6f65491f..1b0fc393 100644 --- a/appwrite/models/specification.py +++ b/appwrite/models/specification.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -24,3 +24,20 @@ class Specification(AppwriteModel): cpus: float = Field(..., alias='cpus') enabled: bool = Field(..., alias='enabled') slug: str = Field(..., alias='slug') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'memory' not in data: + data['memory'] = 0 + if 'cpus' not in data: + data['cpus'] = 0 + if 'enabled' not in data: + data['enabled'] = False + if 'slug' not in data: + data['slug'] = '' + return data diff --git a/appwrite/models/specification_list.py b/appwrite/models/specification_list.py index e05ad6db..80eec518 100644 --- a/appwrite/models/specification_list.py +++ b/appwrite/models/specification_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .specification import Specification @@ -19,3 +19,16 @@ class SpecificationList(AppwriteModel): total: float = Field(..., alias='total') specifications: List[Specification] = Field(..., alias='specifications') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'specifications' not in data: + data['specifications'] = [] + return data diff --git a/appwrite/models/subscriber.py b/appwrite/models/subscriber.py index 80d8e390..707d5b52 100644 --- a/appwrite/models/subscriber.py +++ b/appwrite/models/subscriber.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .target import Target @@ -40,3 +40,28 @@ class Subscriber(AppwriteModel): username: str = Field(..., alias='userName') topicid: str = Field(..., alias='topicId') providertype: str = Field(..., alias='providerType') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'targetId' not in data and 'targetid' not in data: + data['targetId'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'userName' not in data and 'username' not in data: + data['userName'] = '' + if 'topicId' not in data and 'topicid' not in data: + data['topicId'] = '' + if 'providerType' not in data and 'providertype' not in data: + data['providerType'] = '' + return data diff --git a/appwrite/models/subscriber_list.py b/appwrite/models/subscriber_list.py index cb346700..ab3eb500 100644 --- a/appwrite/models/subscriber_list.py +++ b/appwrite/models/subscriber_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .subscriber import Subscriber @@ -19,3 +19,16 @@ class SubscriberList(AppwriteModel): total: float = Field(..., alias='total') subscribers: List[Subscriber] = Field(..., alias='subscribers') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'subscribers' not in data: + data['subscribers'] = [] + return data diff --git a/appwrite/models/table.py b/appwrite/models/table.py index 6e4a5cbf..41c97ef3 100644 --- a/appwrite/models/table.py +++ b/appwrite/models/table.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .column_boolean import ColumnBoolean @@ -88,3 +88,36 @@ class Table(AppwriteModel): indexes: List[ColumnIndex] = Field(..., alias='indexes') bytesmax: float = Field(..., alias='bytesMax') bytesused: float = Field(..., alias='bytesUsed') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if '$permissions' not in data and 'permissions' not in data: + data['$permissions'] = [] + if 'databaseId' not in data and 'databaseid' not in data: + data['databaseId'] = '' + if 'name' not in data: + data['name'] = '' + if 'enabled' not in data: + data['enabled'] = True + if 'rowSecurity' not in data and 'rowsecurity' not in data: + data['rowSecurity'] = False + if 'columns' not in data: + data['columns'] = [] + if 'indexes' not in data: + data['indexes'] = [] + if 'bytesMax' not in data and 'bytesmax' not in data: + data['bytesMax'] = 0 + if 'bytesUsed' not in data and 'bytesused' not in data: + data['bytesUsed'] = 0 + return data diff --git a/appwrite/models/table_list.py b/appwrite/models/table_list.py index 9d8b29f2..a09ee1c8 100644 --- a/appwrite/models/table_list.py +++ b/appwrite/models/table_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .table import Table @@ -19,3 +19,16 @@ class TableList(AppwriteModel): total: float = Field(..., alias='total') tables: List[Table] = Field(..., alias='tables') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'tables' not in data: + data['tables'] = [] + return data diff --git a/appwrite/models/target.py b/appwrite/models/target.py index de38e227..8377844f 100644 --- a/appwrite/models/target.py +++ b/appwrite/models/target.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -39,3 +39,28 @@ class Target(AppwriteModel): providertype: str = Field(..., alias='providerType') identifier: str = Field(..., alias='identifier') expired: bool = Field(..., alias='expired') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'providerType' not in data and 'providertype' not in data: + data['providerType'] = '' + if 'identifier' not in data: + data['identifier'] = '' + if 'expired' not in data: + data['expired'] = False + return data diff --git a/appwrite/models/target_list.py b/appwrite/models/target_list.py index 095aa9bf..69953681 100644 --- a/appwrite/models/target_list.py +++ b/appwrite/models/target_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .target import Target @@ -19,3 +19,16 @@ class TargetList(AppwriteModel): total: float = Field(..., alias='total') targets: List[Target] = Field(..., alias='targets') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'targets' not in data: + data['targets'] = [] + return data diff --git a/appwrite/models/team.py b/appwrite/models/team.py index c1f13ab4..8b2b7209 100644 --- a/appwrite/models/team.py +++ b/appwrite/models/team.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast, Generic, TypeVar, Type -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .preferences import Preferences @@ -34,6 +34,25 @@ class Team(AppwriteModel, Generic[T]): total: float = Field(..., alias='total') prefs: Preferences[T] = Field(..., alias='prefs') + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'total' not in data: + data['total'] = 0 + return data + @classmethod def with_data(cls, data: Dict[str, Any], model_type: Type[T] = dict) -> 'Team[T]': """Create Team instance with typed data.""" diff --git a/appwrite/models/team_list.py b/appwrite/models/team_list.py index 682e09d7..854f942a 100644 --- a/appwrite/models/team_list.py +++ b/appwrite/models/team_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast, Generic, TypeVar, Type -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .team import Team @@ -22,6 +22,19 @@ class TeamList(AppwriteModel, Generic[T]): total: float = Field(..., alias='total') teams: List[Team[T]] = Field(..., alias='teams') + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'teams' not in data: + data['teams'] = [] + return data + @classmethod def with_data(cls, data: Dict[str, Any], model_type: Type[T] = dict) -> 'TeamList[T]': """Create TeamList instance with typed data.""" diff --git a/appwrite/models/token.py b/appwrite/models/token.py index b99233d2..614b43c6 100644 --- a/appwrite/models/token.py +++ b/appwrite/models/token.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -30,3 +30,24 @@ class Token(AppwriteModel): secret: str = Field(..., alias='secret') expire: str = Field(..., alias='expire') phrase: str = Field(..., alias='phrase') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'secret' not in data: + data['secret'] = '' + if 'expire' not in data: + data['expire'] = '' + if 'phrase' not in data: + data['phrase'] = '' + return data diff --git a/appwrite/models/token_secret.py b/appwrite/models/token_secret.py index 6d89eed4..c745ea11 100644 --- a/appwrite/models/token_secret.py +++ b/appwrite/models/token_secret.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -30,3 +30,24 @@ class TokenSecret(AppwriteModel): secret: str = Field(..., alias='secret') expire: str = Field(..., alias='expire') phrase: str = Field(..., alias='phrase') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if 'userId' not in data and 'userid' not in data: + data['userId'] = '' + if 'secret' not in data: + data['secret'] = '' + if 'expire' not in data: + data['expire'] = '' + if 'phrase' not in data: + data['phrase'] = '' + return data diff --git a/appwrite/models/topic.py b/appwrite/models/topic.py index 2e494183..b3566eec 100644 --- a/appwrite/models/topic.py +++ b/appwrite/models/topic.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -29,7 +29,7 @@ class Topic(AppwriteModel): qos : Optional[float] MQTT QoS for delivery on this topic. Null lets the subscriber choose their level. expiry : Optional[float] - Message retention in seconds for offline delivery. + Message retention in seconds for offline delivery. Null inherits the lowest expiry of the project's enabled Appwrite providers, or the 7-day ledger window if none sets one. """ id: str = Field(..., alias='$id') @@ -42,3 +42,28 @@ class Topic(AppwriteModel): subscribe: List[Any] = Field(..., alias='subscribe') qos: Optional[float] = Field(default=None, alias='qos') expiry: Optional[float] = Field(default=None, alias='expiry') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'emailTotal' not in data and 'emailtotal' not in data: + data['emailTotal'] = 0 + if 'smsTotal' not in data and 'smstotal' not in data: + data['smsTotal'] = 0 + if 'pushTotal' not in data and 'pushtotal' not in data: + data['pushTotal'] = 0 + if 'subscribe' not in data: + data['subscribe'] = ['users'] + return data diff --git a/appwrite/models/topic_list.py b/appwrite/models/topic_list.py index e739ccb5..f959597b 100644 --- a/appwrite/models/topic_list.py +++ b/appwrite/models/topic_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .topic import Topic @@ -19,3 +19,16 @@ class TopicList(AppwriteModel): total: float = Field(..., alias='total') topics: List[Topic] = Field(..., alias='topics') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'topics' not in data: + data['topics'] = [] + return data diff --git a/appwrite/models/transaction.py b/appwrite/models/transaction.py index 03461ab3..6936d7eb 100644 --- a/appwrite/models/transaction.py +++ b/appwrite/models/transaction.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -30,3 +30,24 @@ class Transaction(AppwriteModel): status: str = Field(..., alias='status') operations: float = Field(..., alias='operations') expiresat: str = Field(..., alias='expiresAt') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'status' not in data: + data['status'] = 'pending' + if 'operations' not in data: + data['operations'] = 0 + if 'expiresAt' not in data and 'expiresat' not in data: + data['expiresAt'] = '' + return data diff --git a/appwrite/models/transaction_list.py b/appwrite/models/transaction_list.py index a6c7184d..8de6aa8b 100644 --- a/appwrite/models/transaction_list.py +++ b/appwrite/models/transaction_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .transaction import Transaction @@ -19,3 +19,16 @@ class TransactionList(AppwriteModel): total: float = Field(..., alias='total') transactions: List[Transaction] = Field(..., alias='transactions') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'transactions' not in data: + data['transactions'] = [] + return data diff --git a/appwrite/models/usage_billing_plan.py b/appwrite/models/usage_billing_plan.py index 1951161a..cca5b806 100644 --- a/appwrite/models/usage_billing_plan.py +++ b/appwrite/models/usage_billing_plan.py @@ -11,38 +11,38 @@ class UsageBillingPlan(AppwriteModel): Attributes ---------- - bandwidth : AdditionalResource + bandwidth : Optional[AdditionalResource] Bandwidth additional resources - executions : AdditionalResource + executions : Optional[AdditionalResource] Executions additional resources member : Optional[AdditionalResource] Member additional resources - realtime : AdditionalResource + realtime : Optional[AdditionalResource] Realtime additional resources - realtimemessages : AdditionalResource + realtimemessages : Optional[AdditionalResource] Realtime messages additional resources realtimebandwidth : Optional[AdditionalResource] Realtime bandwidth additional resources - storage : AdditionalResource + storage : Optional[AdditionalResource] Storage additional resources - users : AdditionalResource + users : Optional[AdditionalResource] User additional resources - gbhours : AdditionalResource + gbhours : Optional[AdditionalResource] GBHour additional resources - imagetransformations : AdditionalResource + imagetransformations : Optional[AdditionalResource] Image transformation additional resources credits : Optional[AdditionalResource] Credits additional resources """ - bandwidth: AdditionalResource = Field(..., alias='bandwidth') - executions: AdditionalResource = Field(..., alias='executions') + bandwidth: Optional[AdditionalResource] = Field(default=None, alias='bandwidth') + executions: Optional[AdditionalResource] = Field(default=None, alias='executions') member: Optional[AdditionalResource] = Field(default=None, alias='member') - realtime: AdditionalResource = Field(..., alias='realtime') - realtimemessages: AdditionalResource = Field(..., alias='realtimeMessages') + realtime: Optional[AdditionalResource] = Field(default=None, alias='realtime') + realtimemessages: Optional[AdditionalResource] = Field(default=None, alias='realtimeMessages') realtimebandwidth: Optional[AdditionalResource] = Field(default=None, alias='realtimeBandwidth') - storage: AdditionalResource = Field(..., alias='storage') - users: AdditionalResource = Field(..., alias='users') - gbhours: AdditionalResource = Field(..., alias='GBHours') - imagetransformations: AdditionalResource = Field(..., alias='imageTransformations') + storage: Optional[AdditionalResource] = Field(default=None, alias='storage') + users: Optional[AdditionalResource] = Field(default=None, alias='users') + gbhours: Optional[AdditionalResource] = Field(default=None, alias='GBHours') + imagetransformations: Optional[AdditionalResource] = Field(default=None, alias='imageTransformations') credits: Optional[AdditionalResource] = Field(default=None, alias='credits') diff --git a/appwrite/models/user.py b/appwrite/models/user.py index a10e5efc..4a1c1d9a 100644 --- a/appwrite/models/user.py +++ b/appwrite/models/user.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast, Generic, TypeVar, Type -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .algo_argon2 import AlgoArgon2 @@ -115,6 +115,45 @@ class User(AppwriteModel, Generic[T]): impersonator: Optional[bool] = Field(default=None, alias='impersonator') impersonatoruserid: Optional[str] = Field(default=None, alias='impersonatorUserId') + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'registration' not in data: + data['registration'] = '' + if 'status' not in data: + data['status'] = True + if 'labels' not in data: + data['labels'] = [] + if 'passwordUpdate' not in data and 'passwordupdate' not in data: + data['passwordUpdate'] = '' + if 'email' not in data: + data['email'] = '' + if 'phone' not in data: + data['phone'] = '' + if 'emailVerification' not in data and 'emailverification' not in data: + data['emailVerification'] = False + if 'phoneVerification' not in data and 'phoneverification' not in data: + data['phoneVerification'] = False + if 'mfa' not in data: + data['mfa'] = False + if 'targets' not in data: + data['targets'] = [] + if 'accessedAt' not in data and 'accessedat' not in data: + data['accessedAt'] = '' + return data + @classmethod def with_data(cls, data: Dict[str, Any], model_type: Type[T] = dict) -> 'User[T]': """Create User instance with typed data.""" diff --git a/appwrite/models/user_list.py b/appwrite/models/user_list.py index 7c6c7a2d..f6a776cc 100644 --- a/appwrite/models/user_list.py +++ b/appwrite/models/user_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast, Generic, TypeVar, Type -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .user import User @@ -22,6 +22,19 @@ class UserList(AppwriteModel, Generic[T]): total: float = Field(..., alias='total') users: List[User[T]] = Field(..., alias='users') + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'users' not in data: + data['users'] = [] + return data + @classmethod def with_data(cls, data: Dict[str, Any], model_type: Type[T] = dict) -> 'UserList[T]': """Create UserList instance with typed data.""" diff --git a/appwrite/models/variable.py b/appwrite/models/variable.py index c89b1cbc..a50d58f0 100644 --- a/appwrite/models/variable.py +++ b/appwrite/models/variable.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -36,3 +36,28 @@ class Variable(AppwriteModel): secret: bool = Field(..., alias='secret') resourcetype: str = Field(..., alias='resourceType') resourceid: str = Field(..., alias='resourceId') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'key' not in data: + data['key'] = '' + if 'value' not in data: + data['value'] = '' + if 'secret' not in data: + data['secret'] = False + if 'resourceType' not in data and 'resourcetype' not in data: + data['resourceType'] = '' + if 'resourceId' not in data and 'resourceid' not in data: + data['resourceId'] = '' + return data diff --git a/appwrite/models/variable_list.py b/appwrite/models/variable_list.py index 9307112e..05cb01ba 100644 --- a/appwrite/models/variable_list.py +++ b/appwrite/models/variable_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .variable import Variable @@ -19,3 +19,16 @@ class VariableList(AppwriteModel): total: float = Field(..., alias='total') variables: List[Variable] = Field(..., alias='variables') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'variables' not in data: + data['variables'] = [] + return data diff --git a/appwrite/models/vectorsdb_collection.py b/appwrite/models/vectorsdb_collection.py index bfdae1d9..e4ca60ff 100644 --- a/appwrite/models/vectorsdb_collection.py +++ b/appwrite/models/vectorsdb_collection.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .attribute_object import AttributeObject @@ -59,3 +59,38 @@ class VectorsdbCollection(AppwriteModel): bytesmax: float = Field(..., alias='bytesMax') bytesused: float = Field(..., alias='bytesUsed') dimension: float = Field(..., alias='dimension') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if '$permissions' not in data and 'permissions' not in data: + data['$permissions'] = [] + if 'databaseId' not in data and 'databaseid' not in data: + data['databaseId'] = '' + if 'name' not in data: + data['name'] = '' + if 'enabled' not in data: + data['enabled'] = True + if 'documentSecurity' not in data and 'documentsecurity' not in data: + data['documentSecurity'] = False + if 'attributes' not in data: + data['attributes'] = [] + if 'indexes' not in data: + data['indexes'] = [] + if 'bytesMax' not in data and 'bytesmax' not in data: + data['bytesMax'] = 0 + if 'bytesUsed' not in data and 'bytesused' not in data: + data['bytesUsed'] = 0 + if 'dimension' not in data: + data['dimension'] = 0 + return data diff --git a/appwrite/models/vectorsdb_collection_list.py b/appwrite/models/vectorsdb_collection_list.py index 2e930e8d..b26f46a3 100644 --- a/appwrite/models/vectorsdb_collection_list.py +++ b/appwrite/models/vectorsdb_collection_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .vectorsdb_collection import VectorsdbCollection @@ -19,3 +19,16 @@ class VectorsdbCollectionList(AppwriteModel): total: float = Field(..., alias='total') collections: List[VectorsdbCollection] = Field(..., alias='collections') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'collections' not in data: + data['collections'] = [] + return data diff --git a/appwrite/models/waf_rule_bypass.py b/appwrite/models/waf_rule_bypass.py index fe561556..7134f681 100644 --- a/appwrite/models/waf_rule_bypass.py +++ b/appwrite/models/waf_rule_bypass.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.waf_rule_action import WafRuleAction @@ -55,3 +55,38 @@ class WafRuleBypass(AppwriteModel): enabled: bool = Field(..., alias='enabled') conditions: List[Any] = Field(..., alias='conditions') config: Dict[str, Any] = Field(..., alias='config') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'description' not in data: + data['description'] = '' + if 'teamId' not in data and 'teamid' not in data: + data['teamId'] = '' + if 'projectId' not in data and 'projectid' not in data: + data['projectId'] = '' + if 'resourceType' not in data and 'resourcetype' not in data: + data['resourceType'] = 'api' + if 'resourceId' not in data and 'resourceid' not in data: + data['resourceId'] = '' + if 'priority' not in data: + data['priority'] = 0 + if 'enabled' not in data: + data['enabled'] = True + if 'conditions' not in data: + data['conditions'] = [] + if 'config' not in data: + data['config'] = {} + return data diff --git a/appwrite/models/waf_rule_challenge.py b/appwrite/models/waf_rule_challenge.py index 45730853..0c7c7531 100644 --- a/appwrite/models/waf_rule_challenge.py +++ b/appwrite/models/waf_rule_challenge.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.waf_rule_action import WafRuleAction @@ -64,3 +64,44 @@ class WafRuleChallenge(AppwriteModel): challengetype: str = Field(..., alias='challengeType') difficulty: float = Field(..., alias='difficulty') ttl: float = Field(..., alias='ttl') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'description' not in data: + data['description'] = '' + if 'teamId' not in data and 'teamid' not in data: + data['teamId'] = '' + if 'projectId' not in data and 'projectid' not in data: + data['projectId'] = '' + if 'resourceType' not in data and 'resourcetype' not in data: + data['resourceType'] = 'api' + if 'resourceId' not in data and 'resourceid' not in data: + data['resourceId'] = '' + if 'priority' not in data: + data['priority'] = 0 + if 'enabled' not in data: + data['enabled'] = True + if 'conditions' not in data: + data['conditions'] = [] + if 'config' not in data: + data['config'] = {} + if 'challengeType' not in data and 'challengetype' not in data: + data['challengeType'] = 'compute' + if 'difficulty' not in data: + data['difficulty'] = 3 + if 'ttl' not in data: + data['ttl'] = 1800 + return data diff --git a/appwrite/models/waf_rule_deny.py b/appwrite/models/waf_rule_deny.py index 1edafc8b..8ce11701 100644 --- a/appwrite/models/waf_rule_deny.py +++ b/appwrite/models/waf_rule_deny.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.waf_rule_action import WafRuleAction @@ -55,3 +55,38 @@ class WafRuleDeny(AppwriteModel): enabled: bool = Field(..., alias='enabled') conditions: List[Any] = Field(..., alias='conditions') config: Dict[str, Any] = Field(..., alias='config') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'description' not in data: + data['description'] = '' + if 'teamId' not in data and 'teamid' not in data: + data['teamId'] = '' + if 'projectId' not in data and 'projectid' not in data: + data['projectId'] = '' + if 'resourceType' not in data and 'resourcetype' not in data: + data['resourceType'] = 'api' + if 'resourceId' not in data and 'resourceid' not in data: + data['resourceId'] = '' + if 'priority' not in data: + data['priority'] = 0 + if 'enabled' not in data: + data['enabled'] = True + if 'conditions' not in data: + data['conditions'] = [] + if 'config' not in data: + data['config'] = {} + return data diff --git a/appwrite/models/waf_rule_list.py b/appwrite/models/waf_rule_list.py index 418a8543..c5a75c60 100644 --- a/appwrite/models/waf_rule_list.py +++ b/appwrite/models/waf_rule_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .waf_rule_bypass import WafRuleBypass @@ -31,3 +31,16 @@ class WafRuleList(AppwriteModel): WafRuleRedirect, ] ] = Field(..., alias='rules') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'rules' not in data: + data['rules'] = [] + return data diff --git a/appwrite/models/waf_rule_rate_limit.py b/appwrite/models/waf_rule_rate_limit.py index c05cc13c..3e816549 100644 --- a/appwrite/models/waf_rule_rate_limit.py +++ b/appwrite/models/waf_rule_rate_limit.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.waf_rule_action import WafRuleAction @@ -70,3 +70,48 @@ class WafRuleRateLimit(AppwriteModel): key: str = Field(..., alias='key') strategy: str = Field(..., alias='strategy') maxbucketsize: float = Field(..., alias='maxBucketSize') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'description' not in data: + data['description'] = '' + if 'teamId' not in data and 'teamid' not in data: + data['teamId'] = '' + if 'projectId' not in data and 'projectid' not in data: + data['projectId'] = '' + if 'resourceType' not in data and 'resourcetype' not in data: + data['resourceType'] = 'api' + if 'resourceId' not in data and 'resourceid' not in data: + data['resourceId'] = '' + if 'priority' not in data: + data['priority'] = 0 + if 'enabled' not in data: + data['enabled'] = True + if 'conditions' not in data: + data['conditions'] = [] + if 'config' not in data: + data['config'] = {} + if 'limit' not in data: + data['limit'] = 100 + if 'interval' not in data: + data['interval'] = 3600 + if 'key' not in data: + data['key'] = 'ip' + if 'strategy' not in data: + data['strategy'] = 'fixedWindow' + if 'maxBucketSize' not in data and 'maxbucketsize' not in data: + data['maxBucketSize'] = 0 + return data diff --git a/appwrite/models/waf_rule_redirect.py b/appwrite/models/waf_rule_redirect.py index aba9ffa3..434c49eb 100644 --- a/appwrite/models/waf_rule_redirect.py +++ b/appwrite/models/waf_rule_redirect.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from ..enums.waf_rule_action import WafRuleAction @@ -61,3 +61,42 @@ class WafRuleRedirect(AppwriteModel): config: Dict[str, Any] = Field(..., alias='config') location: str = Field(..., alias='location') statuscode: float = Field(..., alias='statusCode') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'description' not in data: + data['description'] = '' + if 'teamId' not in data and 'teamid' not in data: + data['teamId'] = '' + if 'projectId' not in data and 'projectid' not in data: + data['projectId'] = '' + if 'resourceType' not in data and 'resourcetype' not in data: + data['resourceType'] = 'api' + if 'resourceId' not in data and 'resourceid' not in data: + data['resourceId'] = '' + if 'priority' not in data: + data['priority'] = 0 + if 'enabled' not in data: + data['enabled'] = True + if 'conditions' not in data: + data['conditions'] = [] + if 'config' not in data: + data['config'] = {} + if 'location' not in data: + data['location'] = '/' + if 'statusCode' not in data and 'statuscode' not in data: + data['statusCode'] = 302 + return data diff --git a/appwrite/models/webhook.py b/appwrite/models/webhook.py index ede2e0ad..3114336d 100644 --- a/appwrite/models/webhook.py +++ b/appwrite/models/webhook.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel @@ -27,7 +27,7 @@ class Webhook(AppwriteModel): authusername : str HTTP basic authentication username. authpassword : str - HTTP basic authentication password. + HTTP basic authentication password. Write-only: always returned empty. secret : str Signature key which can be used to validate incoming webhook payloads. Only returned on creation and secret rotation. enabled : bool @@ -51,3 +51,38 @@ class Webhook(AppwriteModel): enabled: bool = Field(..., alias='enabled') logs: str = Field(..., alias='logs') attempts: float = Field(..., alias='attempts') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if '$id' not in data and 'id' not in data: + data['$id'] = '' + if '$createdAt' not in data and 'createdat' not in data: + data['$createdAt'] = '' + if '$updatedAt' not in data and 'updatedat' not in data: + data['$updatedAt'] = '' + if 'name' not in data: + data['name'] = '' + if 'url' not in data: + data['url'] = '' + if 'events' not in data: + data['events'] = [] + if 'tls' not in data: + data['tls'] = True + if 'authUsername' not in data and 'authusername' not in data: + data['authUsername'] = '' + if 'authPassword' not in data and 'authpassword' not in data: + data['authPassword'] = '' + if 'secret' not in data: + data['secret'] = '' + if 'enabled' not in data: + data['enabled'] = True + if 'logs' not in data: + data['logs'] = '' + if 'attempts' not in data: + data['attempts'] = 0 + return data diff --git a/appwrite/models/webhook_list.py b/appwrite/models/webhook_list.py index 537ea090..fd42b2e2 100644 --- a/appwrite/models/webhook_list.py +++ b/appwrite/models/webhook_list.py @@ -1,5 +1,5 @@ from typing import Any, Dict, List, Optional, Union, cast -from pydantic import Field, PrivateAttr +from pydantic import Field, PrivateAttr, model_validator from .base_model import AppwriteModel from .webhook import Webhook @@ -19,3 +19,16 @@ class WebhookList(AppwriteModel): total: float = Field(..., alias='total') webhooks: List[Webhook] = Field(..., alias='webhooks') + + @model_validator(mode='before') + @classmethod + def _apply_defaults(cls, data: Any) -> Any: + if not isinstance(data, dict): + return data + + data = dict(data) + if 'total' not in data: + data['total'] = 0 + if 'webhooks' not in data: + data['webhooks'] = [] + return data diff --git a/appwrite/query.py b/appwrite/query.py index 154a19e6..f32bdc9e 100644 --- a/appwrite/query.py +++ b/appwrite/query.py @@ -229,6 +229,20 @@ def elem_match(attribute, queries): """ return str(Query("elemMatch", attribute, [json.loads(query) for query in queries])) + @staticmethod + def relationship(attribute, queries): + """ + Constrain populated related documents on a relationship attribute. + + Args: + attribute: The relationship attribute to query. + queries: Filter, order, select, and pagination queries applied to related documents. + + Returns: + The query string. + """ + return str(Query("relationship", attribute, [json.loads(query) for query in queries])) + @staticmethod def distance_equal(attribute, values, distance, meters=True): return str(Query("distanceEqual", attribute, [[values, distance, meters]])) @@ -288,3 +302,448 @@ def touches(attribute, values): @staticmethod def not_touches(attribute, values): return str(Query("notTouches", attribute, [values])) + + @staticmethod + def count(attribute='*', alias=''): + return str(Query("count", attribute, alias if alias != '' else None)) + + @staticmethod + def count_distinct(attribute, alias=''): + return str(Query("countDistinct", attribute, alias if alias != '' else None)) + + @staticmethod + def sum(attribute, alias=''): + return str(Query("sum", attribute, alias if alias != '' else None)) + + @staticmethod + def avg(attribute, alias=''): + return str(Query("avg", attribute, alias if alias != '' else None)) + + @staticmethod + def min(attribute, alias=''): + return str(Query("min", attribute, alias if alias != '' else None)) + + @staticmethod + def max(attribute, alias=''): + return str(Query("max", attribute, alias if alias != '' else None)) + + @staticmethod + def stddev(attribute, alias=''): + return str(Query("stddev", attribute, alias if alias != '' else None)) + + @staticmethod + def stddev_pop(attribute, alias=''): + return str(Query("stddevPop", attribute, alias if alias != '' else None)) + + @staticmethod + def stddev_samp(attribute, alias=''): + return str(Query("stddevSamp", attribute, alias if alias != '' else None)) + + @staticmethod + def variance(attribute, alias=''): + return str(Query("variance", attribute, alias if alias != '' else None)) + + @staticmethod + def var_pop(attribute, alias=''): + return str(Query("varPop", attribute, alias if alias != '' else None)) + + @staticmethod + def var_samp(attribute, alias=''): + return str(Query("varSamp", attribute, alias if alias != '' else None)) + + @staticmethod + def bit_and(attribute, alias=''): + return str(Query("bitAnd", attribute, alias if alias != '' else None)) + + @staticmethod + def bit_or(attribute, alias=''): + return str(Query("bitOr", attribute, alias if alias != '' else None)) + + @staticmethod + def bit_xor(attribute, alias=''): + return str(Query("bitXor", attribute, alias if alias != '' else None)) + + @staticmethod + def group_by(attributes): + return str(Query("groupBy", None, attributes)) + + @staticmethod + def having(queries): + return str(Query("having", None, [json.loads(query) for query in queries])) + + @staticmethod + def distinct(): + return str(Query("distinct", None, None)) + + @staticmethod + def on(left, right, operator='='): + return str(Query("on", None, [left, operator, right])) + + @staticmethod + def join(table, left, right='', operator='=', alias=''): + return Query._create_join("join", table, left, right, operator, alias) + + @staticmethod + def left_join(table, left, right='', operator='=', alias=''): + return Query._create_join("leftJoin", table, left, right, operator, alias) + + @staticmethod + def right_join(table, left, right='', operator='=', alias=''): + return Query._create_join("rightJoin", table, left, right, operator, alias) + + @staticmethod + def full_outer_join(table, left, right='', operator='=', alias=''): + return Query._create_join("fullOuterJoin", table, left, right, operator, alias) + + @staticmethod + def cross_join(table, alias=''): + return str(Query("crossJoin", table, alias if alias != '' else None)) + + @staticmethod + def covers(attribute, values): + return str(Query("covers", attribute, [values])) + + @staticmethod + def not_covers(attribute, values): + return str(Query("notCovers", attribute, [values])) + + @staticmethod + def spatial_equals(attribute, values): + return str(Query("spatialEquals", attribute, [values])) + + @staticmethod + def not_spatial_equals(attribute, values): + return str(Query("notSpatialEquals", attribute, [values])) + + @staticmethod + def page(page, per_page=25): + if page < 1: + raise ValueError(f'Page must be >= 1, got {page}') + if per_page < 1: + raise ValueError(f'Per page must be >= 1, got {per_page}') + + return [ + Query.limit(per_page), + Query.offset((page - 1) * per_page), + ] + + @staticmethod + def builder(): + return Query.Builder() + + @staticmethod + def _flatten(value): + if isinstance(value, Query.Builder): + return value.build() + if isinstance(value, Query): + return str(value) + if not isinstance(value, list): + return value + + out = [] + changed = False + for item in value: + flat = Query._flatten(item) + if isinstance(item, (Query.Builder, Query)): + if isinstance(flat, list): + out.extend(flat) + else: + out.append(flat) + changed = True + continue + if flat is not item: + changed = True + out.append(flat) + + return out if changed else value + + @staticmethod + def _create_join(method, table, left, right, operator, alias): + if isinstance(left, list): + return Query._nested_join(method, table, '', left) + if isinstance(right, list): + return Query._nested_join(method, table, left, right) + return Query._join(method, table, left, right, operator, alias) + + @staticmethod + def _nested_join(method, table, alias, on): + values = [] + if alias != '': + values.append(alias) + for query in on: + values.append(json.loads(query)) + return str(Query(method, table, values)) + + @staticmethod + def _join(method, table, left, right, operator, alias): + values = [left, operator, right] + if alias != '': + values.append(alias) + return str(Query(method, table, values)) + + class Builder: + def __init__(self): + self._queries = [] + + def build(self): + return list(self._queries) + + def equal(self, attribute, value): + return self._push(Query.equal(attribute, value)) + + def not_equal(self, attribute, value): + return self._push(Query.not_equal(attribute, value)) + + def less_than(self, attribute, value): + return self._push(Query.less_than(attribute, value)) + + def less_than_equal(self, attribute, value): + return self._push(Query.less_than_equal(attribute, value)) + + def greater_than(self, attribute, value): + return self._push(Query.greater_than(attribute, value)) + + def greater_than_equal(self, attribute, value): + return self._push(Query.greater_than_equal(attribute, value)) + + def search(self, attribute, value): + return self._push(Query.search(attribute, value)) + + def is_null(self, attribute): + return self._push(Query.is_null(attribute)) + + def is_not_null(self, attribute): + return self._push(Query.is_not_null(attribute)) + + def between(self, attribute, start, end): + return self._push(Query.between(attribute, start, end)) + + def starts_with(self, attribute, value): + return self._push(Query.starts_with(attribute, value)) + + def ends_with(self, attribute, value): + return self._push(Query.ends_with(attribute, value)) + + def select(self, attributes): + return self._push(Query.select(attributes)) + + def cursor_after(self, id): + return self._push(Query.cursor_after(id)) + + def cursor_before(self, id): + return self._push(Query.cursor_before(id)) + + def order_asc(self, attribute): + return self._push(Query.order_asc(attribute)) + + def order_desc(self, attribute): + return self._push(Query.order_desc(attribute)) + + def order_random(self): + return self._push(Query.order_random()) + + def limit(self, limit): + return self._push(Query.limit(limit)) + + def offset(self, offset): + return self._push(Query.offset(offset)) + + def contains(self, attribute, value): + return self._push(Query.contains(attribute, value)) + + def contains_any(self, attribute, value): + return self._push(Query.contains_any(attribute, value)) + + def contains_all(self, attribute, value): + return self._push(Query.contains_all(attribute, value)) + + def not_contains(self, attribute, value): + return self._push(Query.not_contains(attribute, value)) + + def not_search(self, attribute, value): + return self._push(Query.not_search(attribute, value)) + + def not_between(self, attribute, start, end): + return self._push(Query.not_between(attribute, start, end)) + + def not_starts_with(self, attribute, value): + return self._push(Query.not_starts_with(attribute, value)) + + def not_ends_with(self, attribute, value): + return self._push(Query.not_ends_with(attribute, value)) + + def regex(self, attribute, pattern): + return self._push(Query.regex(attribute, pattern)) + + def exists(self, attributes): + return self._push(Query.exists(attributes)) + + def not_exists(self, attributes): + return self._push(Query.not_exists(attributes)) + + def created_before(self, value): + return self._push(Query.created_before(value)) + + def created_after(self, value): + return self._push(Query.created_after(value)) + + def created_between(self, start, end): + return self._push(Query.created_between(start, end)) + + def updated_before(self, value): + return self._push(Query.updated_before(value)) + + def updated_after(self, value): + return self._push(Query.updated_after(value)) + + def updated_between(self, start, end): + return self._push(Query.updated_between(start, end)) + + def or_queries(self, queries): + return self._push(Query.or_queries(queries)) + + def and_queries(self, queries): + return self._push(Query.and_queries(queries)) + + def elem_match(self, attribute, queries): + return self._push(Query.elem_match(attribute, queries)) + + def relationship(self, attribute, queries): + return self._push(Query.relationship(attribute, queries)) + + def distance_equal(self, attribute, values, distance, meters=True): + return self._push(Query.distance_equal(attribute, values, distance, meters)) + + def distance_not_equal(self, attribute, values, distance, meters=True): + return self._push(Query.distance_not_equal(attribute, values, distance, meters)) + + def distance_greater_than(self, attribute, values, distance, meters=True): + return self._push(Query.distance_greater_than(attribute, values, distance, meters)) + + def distance_less_than(self, attribute, values, distance, meters=True): + return self._push(Query.distance_less_than(attribute, values, distance, meters)) + + def intersects(self, attribute, values): + return self._push(Query.intersects(attribute, values)) + + def not_intersects(self, attribute, values): + return self._push(Query.not_intersects(attribute, values)) + + def crosses(self, attribute, values): + return self._push(Query.crosses(attribute, values)) + + def not_crosses(self, attribute, values): + return self._push(Query.not_crosses(attribute, values)) + + def overlaps(self, attribute, values): + return self._push(Query.overlaps(attribute, values)) + + def not_overlaps(self, attribute, values): + return self._push(Query.not_overlaps(attribute, values)) + + def touches(self, attribute, values): + return self._push(Query.touches(attribute, values)) + + def not_touches(self, attribute, values): + return self._push(Query.not_touches(attribute, values)) + + def count(self, attribute='*', alias=''): + return self._push(Query.count(attribute, alias)) + + def count_distinct(self, attribute, alias=''): + return self._push(Query.count_distinct(attribute, alias)) + + def sum(self, attribute, alias=''): + return self._push(Query.sum(attribute, alias)) + + def avg(self, attribute, alias=''): + return self._push(Query.avg(attribute, alias)) + + def min(self, attribute, alias=''): + return self._push(Query.min(attribute, alias)) + + def max(self, attribute, alias=''): + return self._push(Query.max(attribute, alias)) + + def stddev(self, attribute, alias=''): + return self._push(Query.stddev(attribute, alias)) + + def stddev_pop(self, attribute, alias=''): + return self._push(Query.stddev_pop(attribute, alias)) + + def stddev_samp(self, attribute, alias=''): + return self._push(Query.stddev_samp(attribute, alias)) + + def variance(self, attribute, alias=''): + return self._push(Query.variance(attribute, alias)) + + def var_pop(self, attribute, alias=''): + return self._push(Query.var_pop(attribute, alias)) + + def var_samp(self, attribute, alias=''): + return self._push(Query.var_samp(attribute, alias)) + + def bit_and(self, attribute, alias=''): + return self._push(Query.bit_and(attribute, alias)) + + def bit_or(self, attribute, alias=''): + return self._push(Query.bit_or(attribute, alias)) + + def bit_xor(self, attribute, alias=''): + return self._push(Query.bit_xor(attribute, alias)) + + def group_by(self, attributes): + return self._push(Query.group_by(attributes)) + + def having(self, queries): + return self._push(Query.having(queries)) + + def distinct(self): + return self._push(Query.distinct()) + + def join(self, table, left, right='', operator='=', alias=''): + return self._push(Query.join(table, left, right, operator, alias)) + + def left_join(self, table, left, right='', operator='=', alias=''): + return self._push(Query.left_join(table, left, right, operator, alias)) + + def right_join(self, table, left, right='', operator='=', alias=''): + return self._push(Query.right_join(table, left, right, operator, alias)) + + def full_outer_join(self, table, left, right='', operator='=', alias=''): + return self._push(Query.full_outer_join(table, left, right, operator, alias)) + + def cross_join(self, table, alias=''): + return self._push(Query.cross_join(table, alias)) + + def vector_dot(self, attribute, vector): + return self._push(Query.vector_dot(attribute, vector)) + + def vector_cosine(self, attribute, vector): + return self._push(Query.vector_cosine(attribute, vector)) + + def vector_euclidean(self, attribute, vector): + return self._push(Query.vector_euclidean(attribute, vector)) + + def covers(self, attribute, values): + return self._push(Query.covers(attribute, values)) + + def not_covers(self, attribute, values): + return self._push(Query.not_covers(attribute, values)) + + def spatial_equals(self, attribute, values): + return self._push(Query.spatial_equals(attribute, values)) + + def not_spatial_equals(self, attribute, values): + return self._push(Query.not_spatial_equals(attribute, values)) + + def page(self, page, per_page=25): + return self._push(Query.page(page, per_page)) + + def _push(self, query): + if isinstance(query, list): + self._queries.extend(query) + else: + self._queries.append(query) + + return self diff --git a/appwrite/services/account.py b/appwrite/services/account.py index efacbb40..6891e202 100644 --- a/appwrite/services/account.py +++ b/appwrite/services/account.py @@ -9,7 +9,6 @@ from ..models.oauth2_consent_token_list import Oauth2ConsentTokenList from ..models.oauth2_consent_token import Oauth2ConsentToken from ..models.identity_list import IdentityList -from ..models.log_list import LogList from ..enums.authenticator_type import AuthenticatorType from ..models.mfa_type import MfaType from ..enums.authentication_factor import AuthenticationFactor @@ -203,7 +202,7 @@ def get_consent( api_path = '/account/consents/{consentId}' api_params = {} - if consent_id is None: + if consent_id is None or consent_id == '': raise AppwriteException('Missing required parameter: "consent_id"') api_path = api_path.replace('{consentId}', str(self._normalize_value(consent_id))) @@ -243,7 +242,7 @@ def delete_consent( api_path = '/account/consents/{consentId}' api_params = {} - if consent_id is None: + if consent_id is None or consent_id == '': raise AppwriteException('Missing required parameter: "consent_id"') api_path = api_path.replace('{consentId}', str(self._normalize_value(consent_id))) @@ -290,7 +289,7 @@ def list_consent_tokens( api_path = '/account/consents/{consentId}/tokens' api_params = {} - if consent_id is None: + if consent_id is None or consent_id == '': raise AppwriteException('Missing required parameter: "consent_id"') api_path = api_path.replace('{consentId}', str(self._normalize_value(consent_id))) if queries is not None: @@ -337,9 +336,9 @@ def get_consent_token( api_path = '/account/consents/{consentId}/tokens/{tokenId}' api_params = {} - if consent_id is None: + if consent_id is None or consent_id == '': raise AppwriteException('Missing required parameter: "consent_id"') - if token_id is None: + if token_id is None or token_id == '': raise AppwriteException('Missing required parameter: "token_id"') api_path = api_path.replace('{consentId}', str(self._normalize_value(consent_id))) api_path = api_path.replace('{tokenId}', str(self._normalize_value(token_id))) @@ -383,9 +382,9 @@ def delete_consent_token( api_path = '/account/consents/{consentId}/tokens/{tokenId}' api_params = {} - if consent_id is None: + if consent_id is None or consent_id == '': raise AppwriteException('Missing required parameter: "consent_id"') - if token_id is None: + if token_id is None or token_id == '': raise AppwriteException('Missing required parameter: "token_id"') api_path = api_path.replace('{consentId}', str(self._normalize_value(consent_id))) api_path = api_path.replace('{tokenId}', str(self._normalize_value(token_id))) @@ -523,7 +522,7 @@ def delete_identity( api_path = '/account/identities/{identityId}' api_params = {} - if identity_id is None: + if identity_id is None or identity_id == '': raise AppwriteException('Missing required parameter: "identity_id"') api_path = api_path.replace('{identityId}', str(self._normalize_value(identity_id))) @@ -533,55 +532,12 @@ def delete_identity( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', - }, - api_params, - ) - - return response - - def list_logs( - self, - queries: Optional[List[str]] = None, - total: Optional[bool] = None, - ) -> LogList: - """ - Get the list of latest security activity logs for the currently logged in user. Each log returns user IP address, location and date and time of log. - - Parameters - ---------- - queries : Optional[List[str]] - Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset - total : Optional[bool] - When set to false, the total count returned will be 0 and will not be calculated. - Returns - ------- - LogList - API response as a typed Pydantic model - - Raises - ------ - AppwriteException - If API request fails - """ - - api_path = '/account/logs' - api_params = {} - if queries is not None: - api_params['queries'] = self._normalize_value(queries) - if total is not None: - api_params['total'] = self._normalize_value(total) - - response = self.client.call( - 'get', - api_path, - { - 'X-Appwrite-Project': self.client.get_config('project'), 'accept': 'application/json', }, api_params, ) - return self._parse_response(response, model=LogList) + return response def update_mfa( self, @@ -754,6 +710,7 @@ def delete_mfa_authenticator( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -1742,6 +1699,7 @@ def delete_sessions( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -1787,7 +1745,7 @@ def create_email_password_session( duration: Optional[float] = None, ) -> Session: """ - Allow the user to login into their account by providing a valid email and password combination. This route will create a new session for the user. + Allow the user to login into their account by providing a valid email and password combination. This route will create a new session for the user. Use the optional `duration` parameter to create a shorter session, for example when the user doesn't choose "remember me". It must be at least 60 seconds and cannot exceed the project maximum session length. A user is limited to 10 active sessions at a time by default. [Learn more about session limits](https://appwrite.io/docs/authentication-security#limits). @@ -2082,7 +2040,7 @@ def get_session( api_path = '/account/sessions/{sessionId}' api_params = {} - if session_id is None: + if session_id is None or session_id == '': raise AppwriteException('Missing required parameter: "session_id"') api_path = api_path.replace('{sessionId}', str(self._normalize_value(session_id))) @@ -2122,7 +2080,7 @@ def update_session( api_path = '/account/sessions/{sessionId}' api_params = {} - if session_id is None: + if session_id is None or session_id == '': raise AppwriteException('Missing required parameter: "session_id"') api_path = api_path.replace('{sessionId}', str(self._normalize_value(session_id))) @@ -2163,7 +2121,7 @@ def delete_session( api_path = '/account/sessions/{sessionId}' api_params = {} - if session_id is None: + if session_id is None or session_id == '': raise AppwriteException('Missing required parameter: "session_id"') api_path = api_path.replace('{sessionId}', str(self._normalize_value(session_id))) @@ -2173,6 +2131,7 @@ def delete_session( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -2344,12 +2303,14 @@ def create_o_auth2_token( If authentication succeeds, `userId` and `secret` of a token will be appended to the success URL as query parameters. These can be used to create a new session using the [Create session](https://appwrite.io/docs/references/cloud/client-web/account#createSession) endpoint. + If there is already an active session, the OAuth2 identity is attached to the logged-in account and that session stays active until the token is exchanged for a new one. + A user is limited to 10 active sessions at a time by default. [Learn more about session limits](https://appwrite.io/docs/authentication-security#limits). Parameters ---------- provider : OAuthProvider - OAuth2 Provider. Currently, supported providers are: amazon, apple, appwrite, auth0, authentik, autodesk, bitbucket, bitly, box, cloudflare, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, fusionauth, github, gitlab, google, huggingface, keycloak, kick, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, resend, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, x, yahoo, yammer, yandex, zoho, zoom. + OAuth2 Provider. Currently, supported providers are: amazon, apple, appwrite, auth0, authentik, autodesk, bitbucket, bitly, box, cloudflare, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, fusionauth, github, gitlab, google, huggingface, kakao, keycloak, kick, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, resend, salesforce, slack, spotify, stripe, tiktok, tradeshift, tradeshiftBox, twitch, webflow, wordpress, x, yahoo, yammer, yandex, zoho, zoom. success : Optional[str] URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https://cheatsheetseries.owasp.org/cheatsheets/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API. failure : Optional[str] diff --git a/appwrite/services/activities.py b/appwrite/services/activities.py index 9ef1b8d8..1c33eeef 100644 --- a/appwrite/services/activities.py +++ b/appwrite/services/activities.py @@ -75,7 +75,7 @@ def get_event( api_path = '/activities/events/{eventId}' api_params = {} - if event_id is None: + if event_id is None or event_id == '': raise AppwriteException('Missing required parameter: "event_id"') api_path = api_path.replace('{eventId}', str(self._normalize_value(event_id))) diff --git a/appwrite/services/advisor.py b/appwrite/services/advisor.py index 4afa6aa6..194d0b7a 100644 --- a/appwrite/services/advisor.py +++ b/appwrite/services/advisor.py @@ -82,7 +82,7 @@ def get_report( api_path = '/reports/{reportId}' api_params = {} - if report_id is None: + if report_id is None or report_id == '': raise AppwriteException('Missing required parameter: "report_id"') api_path = api_path.replace('{reportId}', str(self._normalize_value(report_id))) @@ -122,7 +122,7 @@ def delete_report( api_path = '/reports/{reportId}' api_params = {} - if report_id is None: + if report_id is None or report_id == '': raise AppwriteException('Missing required parameter: "report_id"') api_path = api_path.replace('{reportId}', str(self._normalize_value(report_id))) @@ -132,6 +132,7 @@ def delete_report( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -168,7 +169,7 @@ def list_insights( api_path = '/reports/{reportId}/insights' api_params = {} - if report_id is None: + if report_id is None or report_id == '': raise AppwriteException('Missing required parameter: "report_id"') api_path = api_path.replace('{reportId}', str(self._normalize_value(report_id))) if queries is not None: @@ -215,9 +216,9 @@ def get_insight( api_path = '/reports/{reportId}/insights/{insightId}' api_params = {} - if report_id is None: + if report_id is None or report_id == '': raise AppwriteException('Missing required parameter: "report_id"') - if insight_id is None: + if insight_id is None or insight_id == '': raise AppwriteException('Missing required parameter: "insight_id"') api_path = api_path.replace('{reportId}', str(self._normalize_value(report_id))) api_path = api_path.replace('{insightId}', str(self._normalize_value(insight_id))) diff --git a/appwrite/services/apps.py b/appwrite/services/apps.py index 71b5b2ca..6a3439a6 100644 --- a/appwrite/services/apps.py +++ b/appwrite/services/apps.py @@ -284,7 +284,7 @@ def get( api_path = '/apps/{appId}' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) @@ -381,7 +381,7 @@ def update( api_path = '/apps/{appId}' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -461,7 +461,7 @@ def delete( api_path = '/apps/{appId}' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) @@ -508,7 +508,7 @@ def list_installations( api_path = '/apps/{appId}/installations' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) if queries is not None: @@ -555,9 +555,9 @@ def get_installation( api_path = '/apps/{appId}/installations/{installationId}' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') - if installation_id is None: + if installation_id is None or installation_id == '': raise AppwriteException('Missing required parameter: "installation_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) api_path = api_path.replace('{installationId}', str(self._normalize_value(installation_id))) @@ -601,9 +601,9 @@ def delete_installation( api_path = '/apps/{appId}/installations/{installationId}' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') - if installation_id is None: + if installation_id is None or installation_id == '': raise AppwriteException('Missing required parameter: "installation_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) api_path = api_path.replace('{installationId}', str(self._normalize_value(installation_id))) @@ -648,9 +648,9 @@ def create_installation_token( api_path = '/apps/{appId}/installations/{installationId}/tokens' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') - if installation_id is None: + if installation_id is None or installation_id == '': raise AppwriteException('Missing required parameter: "installation_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) api_path = api_path.replace('{installationId}', str(self._normalize_value(installation_id))) @@ -698,7 +698,7 @@ def list_keys( api_path = '/apps/{appId}/keys' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) if queries is not None: @@ -742,7 +742,7 @@ def create_key( api_path = '/apps/{appId}/keys' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) @@ -786,9 +786,9 @@ def get_key( api_path = '/apps/{appId}/keys/{keyId}' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') - if key_id is None: + if key_id is None or key_id == '': raise AppwriteException('Missing required parameter: "key_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) api_path = api_path.replace('{keyId}', str(self._normalize_value(key_id))) @@ -832,9 +832,9 @@ def delete_key( api_path = '/apps/{appId}/keys/{keyId}' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') - if key_id is None: + if key_id is None or key_id == '': raise AppwriteException('Missing required parameter: "key_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) api_path = api_path.replace('{keyId}', str(self._normalize_value(key_id))) @@ -865,7 +865,7 @@ def update_labels( app_id : str Application unique ID. labels : List[str] - Array of application labels. Replaces the previous labels. Maximum of 1000 labels are allowed, each up to 36 alphanumeric characters long. + Array of application labels. Replaces the previous labels. Maximum of 1000 labels are allowed, each up to 36 alphanumeric characters long. Reserved labels are rejected. Returns ------- App @@ -879,7 +879,7 @@ def update_labels( api_path = '/apps/{appId}/labels' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') if labels is None: raise AppwriteException('Missing required parameter: "labels"') @@ -929,7 +929,7 @@ def list_secrets( api_path = '/apps/{appId}/secrets' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) if queries is not None: @@ -973,7 +973,7 @@ def create_secret( api_path = '/apps/{appId}/secrets' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) @@ -1017,9 +1017,9 @@ def get_secret( api_path = '/apps/{appId}/secrets/{secretId}' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') - if secret_id is None: + if secret_id is None or secret_id == '': raise AppwriteException('Missing required parameter: "secret_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) api_path = api_path.replace('{secretId}', str(self._normalize_value(secret_id))) @@ -1063,9 +1063,9 @@ def delete_secret( api_path = '/apps/{appId}/secrets/{secretId}' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') - if secret_id is None: + if secret_id is None or secret_id == '': raise AppwriteException('Missing required parameter: "secret_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) api_path = api_path.replace('{secretId}', str(self._normalize_value(secret_id))) @@ -1110,7 +1110,7 @@ def update_team( api_path = '/apps/{appId}/team' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') if team_id is None: raise AppwriteException('Missing required parameter: "team_id"') @@ -1154,7 +1154,7 @@ def delete_tokens( api_path = '/apps/{appId}/tokens' api_params = {} - if app_id is None: + if app_id is None or app_id == '': raise AppwriteException('Missing required parameter: "app_id"') api_path = api_path.replace('{appId}', str(self._normalize_value(app_id))) diff --git a/appwrite/services/avatars.py b/appwrite/services/avatars.py index 4e735b86..a01b4baf 100644 --- a/appwrite/services/avatars.py +++ b/appwrite/services/avatars.py @@ -358,7 +358,7 @@ def get_photo( name: Optional[str] = None, ) -> bytes: """ - Returns the best available profile photo for a user. The endpoint tries each source in priority order and returns the first successful result: OAuth2 identity photo, Gravatar, Libravatar, Appwrite Initials, built-in static fallback. + Returns the best available profile photo for a user. The endpoint tries each source in priority order and returns the first successful result: a custom uploaded photo (see avatars.updatePhoto), OAuth2 identity photo, Gravatar, Libravatar, Appwrite Initials, built-in static fallback. Passing `userId` — `current()` for the authenticated user — resolves the photo from everything known about that user: identity photos, email, and name. An explicit `emailHash` or `name` then overrides just that value, and the user's remaining sources stay in the chain. Without `userId`, passing `emailHash` and/or `name` resolves the avatar from those values alone: the hash is looked up on Gravatar and Libravatar, the name is rendered as initials, and the session user stays out of the chain so their own photo never shadows the avatar being asked for. When nothing is passed, the photo resolves for the currently authenticated user. Emails are only ever accepted pre-hashed, so no address ends up in a URL. @@ -600,7 +600,7 @@ def get_screenshot( url : str Website URL which you want to capture. headers : Optional[Dict[str, Any]] - HTTP headers to send with the browser request. Defaults to empty. + HTTP headers to send with the browser request. Only Accept and Accept-Language are allowed. Defaults to empty. viewport_width : Optional[float] Browser viewport width. Pass an integer between 1 to 1920. Defaults to 1280. viewport_height : Optional[float] diff --git a/appwrite/services/backups.py b/appwrite/services/backups.py index 4d40755e..c6e75e98 100644 --- a/appwrite/services/backups.py +++ b/appwrite/services/backups.py @@ -126,7 +126,7 @@ def get_archive( api_path = '/backups/archives/{archiveId}' api_params = {} - if archive_id is None: + if archive_id is None or archive_id == '': raise AppwriteException('Missing required parameter: "archive_id"') api_path = api_path.replace('{archiveId}', str(self._normalize_value(archive_id))) @@ -166,7 +166,7 @@ def delete_archive( api_path = '/backups/archives/{archiveId}' api_params = {} - if archive_id is None: + if archive_id is None or archive_id == '': raise AppwriteException('Missing required parameter: "archive_id"') api_path = api_path.replace('{archiveId}', str(self._normalize_value(archive_id))) @@ -320,7 +320,7 @@ def get_policy( api_path = '/backups/policies/{policyId}' api_params = {} - if policy_id is None: + if policy_id is None or policy_id == '': raise AppwriteException('Missing required parameter: "policy_id"') api_path = api_path.replace('{policyId}', str(self._normalize_value(policy_id))) @@ -372,7 +372,7 @@ def update_policy( api_path = '/backups/policies/{policyId}' api_params = {} - if policy_id is None: + if policy_id is None or policy_id == '': raise AppwriteException('Missing required parameter: "policy_id"') api_path = api_path.replace('{policyId}', str(self._normalize_value(policy_id))) if name is not None: @@ -421,7 +421,7 @@ def delete_policy( api_path = '/backups/policies/{policyId}' api_params = {} - if policy_id is None: + if policy_id is None or policy_id == '': raise AppwriteException('Missing required parameter: "policy_id"') api_path = api_path.replace('{policyId}', str(self._normalize_value(policy_id))) @@ -566,7 +566,7 @@ def get_restoration( api_path = '/backups/restorations/{restorationId}' api_params = {} - if restoration_id is None: + if restoration_id is None or restoration_id == '': raise AppwriteException('Missing required parameter: "restoration_id"') api_path = api_path.replace('{restorationId}', str(self._normalize_value(restoration_id))) diff --git a/appwrite/services/databases.py b/appwrite/services/databases.py index 83e13410..5e5fa631 100644 --- a/appwrite/services/databases.py +++ b/appwrite/services/databases.py @@ -269,7 +269,7 @@ def get_transaction( api_path = '/databases/transactions/{transactionId}' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) @@ -318,7 +318,7 @@ def update_transaction( api_path = '/databases/transactions/{transactionId}' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) if commit is not None: @@ -366,7 +366,7 @@ def delete_transaction( api_path = '/databases/transactions/{transactionId}' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) @@ -376,6 +376,7 @@ def delete_transaction( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -412,7 +413,7 @@ def create_operations( api_path = '/databases/transactions/{transactionId}/operations' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) if operations is not None: @@ -458,7 +459,7 @@ def get( api_path = '/databases/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -507,7 +508,7 @@ def update( api_path = '/databases/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if name is not None: @@ -555,7 +556,7 @@ def delete( api_path = '/databases/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -565,6 +566,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -607,7 +609,7 @@ def list_collections( api_path = '/databases/{databaseId}/collections' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if queries is not None: @@ -663,7 +665,7 @@ def create_collection( attributes : Optional[List[Dict[str, Any]]] Array of attribute definitions to create. Each attribute should contain: key (string), type (string: string, varchar, text, mediumtext, longtext, integer, bigint, double, boolean, datetime, point, linestring, polygon, email, url, ip, enum), size (integer, required for string and varchar types), required (boolean, optional), default (mixed, optional), array (boolean, optional), and type-specific options. indexes : Optional[List[Dict[str, Any]]] - Array of index definitions to create. Each index should contain: key (string), type (string: key, fulltext, unique, spatial), attributes (array of attribute keys), orders (array of ASC/DESC, optional), and lengths (array of integers, optional). + Array of index definitions to create. Each index should contain: key (string), type (string: key, fulltext, unique, spatial, trigram), attributes (array of attribute keys), orders (array of ASC/DESC, optional), and lengths (array of integers, optional). Returns ------- Collection @@ -677,7 +679,7 @@ def create_collection( api_path = '/databases/{databaseId}/collections' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if collection_id is None: raise AppwriteException('Missing required parameter: "collection_id"') @@ -740,9 +742,9 @@ def get_collection( api_path = '/databases/{databaseId}/collections/{collectionId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -804,9 +806,9 @@ def update_collection( api_path = '/databases/{databaseId}/collections/{collectionId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -864,9 +866,9 @@ def delete_collection( api_path = '/databases/{databaseId}/collections/{collectionId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -877,6 +879,7 @@ def delete_collection( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -919,9 +922,9 @@ def list_attributes( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -990,9 +993,9 @@ def create_big_int_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/bigint' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1072,11 +1075,11 @@ def update_big_int_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/bigint/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -1147,9 +1150,9 @@ def create_boolean_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/boolean' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1219,11 +1222,11 @@ def update_boolean_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/boolean/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -1290,9 +1293,9 @@ def create_datetime_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/datetime' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1362,11 +1365,11 @@ def update_datetime_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/datetime/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -1433,9 +1436,9 @@ def create_email_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/email' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1505,11 +1508,11 @@ def update_email_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/email/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -1579,9 +1582,9 @@ def create_enum_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/enum' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1657,11 +1660,11 @@ def update_enum_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/enum/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if elements is None: raise AppwriteException('Missing required parameter: "elements"') @@ -1737,9 +1740,9 @@ def create_float_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/float' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1819,11 +1822,11 @@ def update_float_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/float/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -1900,9 +1903,9 @@ def create_integer_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/integer' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1982,11 +1985,11 @@ def update_integer_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/integer/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2057,9 +2060,9 @@ def create_ip_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/ip' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2129,11 +2132,11 @@ def update_ip_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/ip/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2197,9 +2200,9 @@ def create_line_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/line' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2267,11 +2270,11 @@ def update_line_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/line/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2342,9 +2345,9 @@ def create_longtext_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/longtext' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2416,11 +2419,11 @@ def update_longtext_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/longtext/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2490,9 +2493,9 @@ def create_mediumtext_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/mediumtext' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2564,11 +2567,11 @@ def update_mediumtext_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/mediumtext/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2632,9 +2635,9 @@ def create_point_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/point' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2702,11 +2705,11 @@ def update_point_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/point/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2771,9 +2774,9 @@ def create_polygon_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/polygon' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2841,11 +2844,11 @@ def update_polygon_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/polygon/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2919,9 +2922,9 @@ def create_relationship_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/relationship' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if related_collection_id is None: raise AppwriteException('Missing required parameter: "related_collection_id"') @@ -2992,11 +2995,11 @@ def update_relationship_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/relationship/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -3067,9 +3070,9 @@ def create_string_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/string' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -3147,11 +3150,11 @@ def update_string_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/string/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -3223,9 +3226,9 @@ def create_text_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/text' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -3297,11 +3300,11 @@ def update_text_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/text/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -3368,9 +3371,9 @@ def create_url_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/url' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -3440,11 +3443,11 @@ def update_url_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/url/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -3517,9 +3520,9 @@ def create_varchar_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/varchar' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -3597,11 +3600,11 @@ def update_varchar_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/varchar/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -3636,6 +3639,7 @@ def get_attribute( key: str, ) -> Union[ AttributeBoolean, + AttributeBigint, AttributeInteger, AttributeFloat, AttributeEmail, @@ -3644,6 +3648,13 @@ def get_attribute( AttributeIp, AttributeDatetime, AttributeRelationship, + AttributePoint, + AttributeLine, + AttributePolygon, + AttributeVarchar, + AttributeText, + AttributeMediumtext, + AttributeLongtext, AttributeString, ]: """ @@ -3661,7 +3672,7 @@ def get_attribute( Attribute Key. Returns ------- - Union[AttributeBoolean, AttributeInteger, AttributeFloat, AttributeEmail, AttributeEnum, AttributeUrl, AttributeIp, AttributeDatetime, AttributeRelationship, AttributeString] + Union[AttributeBoolean, AttributeBigint, AttributeInteger, AttributeFloat, AttributeEmail, AttributeEnum, AttributeUrl, AttributeIp, AttributeDatetime, AttributeRelationship, AttributePoint, AttributeLine, AttributePolygon, AttributeVarchar, AttributeText, AttributeMediumtext, AttributeLongtext, AttributeString] API response as one of the typed response models Raises @@ -3672,11 +3683,11 @@ def get_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -3709,6 +3720,9 @@ def get_attribute( if response.get('type') == 'boolean': return self._parse_response(response, model=AttributeBoolean) + if response.get('type') == 'bigint': + return self._parse_response(response, model=AttributeBigint) + if response.get('type') == 'integer': return self._parse_response(response, model=AttributeInteger) @@ -3721,6 +3735,27 @@ def get_attribute( if response.get('type') == 'relationship': return self._parse_response(response, model=AttributeRelationship) + if response.get('type') == 'point': + return self._parse_response(response, model=AttributePoint) + + if response.get('type') == 'linestring': + return self._parse_response(response, model=AttributeLine) + + if response.get('type') == 'polygon': + return self._parse_response(response, model=AttributePolygon) + + if response.get('type') == 'varchar': + return self._parse_response(response, model=AttributeVarchar) + + if response.get('type') == 'text': + return self._parse_response(response, model=AttributeText) + + if response.get('type') == 'mediumtext': + return self._parse_response(response, model=AttributeMediumtext) + + if response.get('type') == 'longtext': + return self._parse_response(response, model=AttributeLongtext) + if response.get('type') == 'string': return self._parse_response(response, model=AttributeString) @@ -3759,11 +3794,11 @@ def delete_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/attributes/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -3775,6 +3810,7 @@ def delete_attribute( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -3827,9 +3863,9 @@ def list_documents( api_path = '/databases/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -3900,9 +3936,9 @@ def create_document( api_path = '/databases/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if document_id is None: raise AppwriteException('Missing required parameter: "document_id"') @@ -3970,9 +4006,9 @@ def create_documents( api_path = '/databases/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if documents is None: raise AppwriteException('Missing required parameter: "documents"') @@ -4035,9 +4071,9 @@ def upsert_documents( api_path = '/databases/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if documents is None: raise AppwriteException('Missing required parameter: "documents"') @@ -4103,9 +4139,9 @@ def update_documents( api_path = '/databases/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -4169,9 +4205,9 @@ def delete_documents( api_path = '/databases/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -4236,11 +4272,11 @@ def get_document( api_path = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -4308,11 +4344,11 @@ def upsert_document( api_path = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -4383,11 +4419,11 @@ def update_document( api_path = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -4448,11 +4484,11 @@ def delete_document( api_path = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -4466,6 +4502,7 @@ def delete_document( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -4521,13 +4558,13 @@ def decrement_document_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}/{attribute}/decrement' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') - if attribute is None: + if attribute is None or attribute == '': raise AppwriteException('Missing required parameter: "attribute"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -4602,13 +4639,13 @@ def increment_document_attribute( api_path = '/databases/{databaseId}/collections/{collectionId}/documents/{documentId}/{attribute}/increment' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') - if attribute is None: + if attribute is None or attribute == '': raise AppwriteException('Missing required parameter: "attribute"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -4670,9 +4707,9 @@ def list_indexes( api_path = '/databases/{databaseId}/collections/{collectionId}/indexes' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -4706,7 +4743,7 @@ def create_index( ) -> Index: """ Creates an index on the attributes listed. Your index should include all the attributes you will query in a single request. - Attributes can be `key`, `fulltext`, and `unique`. + Attributes can be `key`, `fulltext`, `unique`, `spatial`, and `trigram`. `trigram` is only available on PostgreSQL and lets `contains`, `startsWith`, and `endsWith` queries on string attributes use an index. .. deprecated::1.8.0 This API has been deprecated since 1.8.0. Please use `tablesDB.create_index` instead. @@ -4739,9 +4776,9 @@ def create_index( api_path = '/databases/{databaseId}/collections/{collectionId}/indexes' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -4805,11 +4842,11 @@ def get_index( api_path = '/databases/{databaseId}/collections/{collectionId}/indexes/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -4860,11 +4897,11 @@ def delete_index( api_path = '/databases/{databaseId}/collections/{collectionId}/indexes/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -4876,6 +4913,7 @@ def delete_index( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) diff --git a/appwrite/services/documents_db.py b/appwrite/services/documents_db.py index c242c0fb..ecef7255 100644 --- a/appwrite/services/documents_db.py +++ b/appwrite/services/documents_db.py @@ -144,7 +144,7 @@ def list_specifications( self, ) -> DedicatedDatabaseSpecificationList: """ - List the dedicated database specifications available on the current plan. Each specification reports its resource limits, pricing, and whether it is enabled for the organization. + List the dedicated database specifications available on the current plan. Each specification reports its resource limits, its own prices and overage rates, and whether it is enabled for the organization. Returns ------- DedicatedDatabaseSpecificationList @@ -279,7 +279,7 @@ def get_transaction( api_path = '/documentsdb/transactions/{transactionId}' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) @@ -325,7 +325,7 @@ def update_transaction( api_path = '/documentsdb/transactions/{transactionId}' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) if commit is not None: @@ -370,7 +370,7 @@ def delete_transaction( api_path = '/documentsdb/transactions/{transactionId}' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) @@ -380,6 +380,7 @@ def delete_transaction( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -413,7 +414,7 @@ def create_operations( api_path = '/documentsdb/transactions/{transactionId}/operations' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) if operations is not None: @@ -456,7 +457,7 @@ def get( api_path = '/documentsdb/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -511,7 +512,7 @@ def update( api_path = '/documentsdb/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -563,7 +564,7 @@ def delete( api_path = '/documentsdb/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -573,6 +574,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -612,7 +614,7 @@ def list_collections( api_path = '/documentsdb/{databaseId}/collections' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if queries is not None: @@ -679,7 +681,7 @@ def create_collection( api_path = '/documentsdb/{databaseId}/collections' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if collection_id is None: raise AppwriteException('Missing required parameter: "collection_id"') @@ -739,9 +741,9 @@ def get_collection( api_path = '/documentsdb/{databaseId}/collections/{collectionId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -800,9 +802,9 @@ def update_collection( api_path = '/documentsdb/{databaseId}/collections/{collectionId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -858,9 +860,9 @@ def delete_collection( api_path = '/documentsdb/{databaseId}/collections/{collectionId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -871,6 +873,7 @@ def delete_collection( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -920,9 +923,9 @@ def list_documents( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -990,9 +993,9 @@ def create_document( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if document_id is None: raise AppwriteException('Missing required parameter: "document_id"') @@ -1057,9 +1060,9 @@ def create_documents( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if documents is None: raise AppwriteException('Missing required parameter: "documents"') @@ -1119,9 +1122,9 @@ def upsert_documents( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if documents is None: raise AppwriteException('Missing required parameter: "documents"') @@ -1184,9 +1187,9 @@ def update_documents( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1247,9 +1250,9 @@ def delete_documents( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1311,11 +1314,11 @@ def get_document( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/documents/{documentId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1380,11 +1383,11 @@ def upsert_document( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/documents/{documentId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1452,11 +1455,11 @@ def update_document( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/documents/{documentId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1514,11 +1517,11 @@ def delete_document( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/documents/{documentId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1532,6 +1535,7 @@ def delete_document( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -1584,13 +1588,13 @@ def decrement_document_attribute( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/documents/{documentId}/{attribute}/decrement' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') - if attribute is None: + if attribute is None or attribute == '': raise AppwriteException('Missing required parameter: "attribute"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1662,13 +1666,13 @@ def increment_document_attribute( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/documents/{documentId}/{attribute}/increment' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') - if attribute is None: + if attribute is None or attribute == '': raise AppwriteException('Missing required parameter: "attribute"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1727,9 +1731,9 @@ def list_indexes( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/indexes' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1793,9 +1797,9 @@ def create_index( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/indexes' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1856,11 +1860,11 @@ def get_index( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/indexes/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1908,11 +1912,11 @@ def delete_index( api_path = '/documentsdb/{databaseId}/collections/{collectionId}/indexes/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1924,6 +1928,7 @@ def delete_index( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -1957,7 +1962,7 @@ def create_failover( api_path = '/documentsdb/{databaseId}/failovers' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if target_replica_id is not None: @@ -2009,7 +2014,7 @@ def list_operations( api_path = '/documentsdb/{databaseId}/operations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if status is not None: @@ -2055,7 +2060,7 @@ def get_replicas( api_path = '/documentsdb/{databaseId}/replicas' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -2095,7 +2100,7 @@ def get_status( api_path = '/documentsdb/{databaseId}/status' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) diff --git a/appwrite/services/functions.py b/appwrite/services/functions.py index 13253dc2..4a7b0ca7 100644 --- a/appwrite/services/functions.py +++ b/appwrite/services/functions.py @@ -336,7 +336,7 @@ def get( api_path = '/functions/{functionId}' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) @@ -377,6 +377,7 @@ def update( runtime_specification: Optional[str] = None, deployment_retention: Optional[float] = None, interval: Optional[float] = None, + email_enabled: Optional[bool] = None, ) -> Function: """ Update function by its unique ID. @@ -429,6 +430,8 @@ def update( Days to keep non-active deployments before deletion. Value 0 means all deployments will be kept. interval : Optional[float] Minutes between scheduled executions. Appwrite picks when within each interval the function runs. Use 0 to disable. Cannot be combined with schedule. When omitted, the current interval is kept unless schedule is set. + email_enabled : Optional[bool] + Enable inbound email triggering for this function. When false or omitted on create, SMTP recipients are rejected. Opt-in; default is off. Returns ------- Function @@ -442,7 +445,7 @@ def update( api_path = '/functions/{functionId}' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -490,6 +493,8 @@ def update( api_params['deploymentRetention'] = self._normalize_value(deployment_retention) if interval is not None: api_params['interval'] = self._normalize_value(interval) + if email_enabled is not None: + api_params['emailEnabled'] = self._normalize_value(email_enabled) response = self.client.call( 'put', @@ -528,7 +533,7 @@ def delete( api_path = '/functions/{functionId}' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) @@ -538,6 +543,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -571,7 +577,7 @@ def update_function_deployment( api_path = '/functions/{functionId}/deployment' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') if deployment_id is None: raise AppwriteException('Missing required parameter: "deployment_id"') @@ -624,7 +630,7 @@ def list_deployments( api_path = '/functions/{functionId}/deployments' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) if queries is not None: @@ -690,7 +696,7 @@ def create_deployment( api_path = '/functions/{functionId}/deployments' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') if code is None: raise AppwriteException('Missing required parameter: "code"') @@ -719,6 +725,7 @@ def create_deployment( param_name, on_progress, upload_id, + method='post', ) return self._parse_response(response, model=Deployment) @@ -753,7 +760,7 @@ def create_duplicate_deployment( api_path = '/functions/{functionId}/deployments/duplicate' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') if deployment_id is None: raise AppwriteException('Missing required parameter: "deployment_id"') @@ -819,7 +826,7 @@ def create_template_deployment( api_path = '/functions/{functionId}/deployments/template' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') if repository is None: raise AppwriteException('Missing required parameter: "repository"') @@ -888,7 +895,7 @@ def create_vcs_deployment( api_path = '/functions/{functionId}/deployments/vcs' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') if type is None: raise AppwriteException('Missing required parameter: "type"') @@ -940,9 +947,9 @@ def get_deployment( api_path = '/functions/{functionId}/deployments/{deploymentId}' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') - if deployment_id is None: + if deployment_id is None or deployment_id == '': raise AppwriteException('Missing required parameter: "deployment_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) api_path = api_path.replace('{deploymentId}', str(self._normalize_value(deployment_id))) @@ -986,9 +993,9 @@ def delete_deployment( api_path = '/functions/{functionId}/deployments/{deploymentId}' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') - if deployment_id is None: + if deployment_id is None or deployment_id == '': raise AppwriteException('Missing required parameter: "deployment_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) api_path = api_path.replace('{deploymentId}', str(self._normalize_value(deployment_id))) @@ -999,6 +1006,7 @@ def delete_deployment( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -1038,9 +1046,9 @@ def get_deployment_download( api_path = '/functions/{functionId}/deployments/{deploymentId}/download' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') - if deployment_id is None: + if deployment_id is None or deployment_id == '': raise AppwriteException('Missing required parameter: "deployment_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) api_path = api_path.replace('{deploymentId}', str(self._normalize_value(deployment_id))) @@ -1088,9 +1096,9 @@ def update_deployment_status( api_path = '/functions/{functionId}/deployments/{deploymentId}/status' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') - if deployment_id is None: + if deployment_id is None or deployment_id == '': raise AppwriteException('Missing required parameter: "deployment_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) api_path = api_path.replace('{deploymentId}', str(self._normalize_value(deployment_id))) @@ -1138,7 +1146,7 @@ def list_executions( api_path = '/functions/{functionId}/executions' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) if queries is not None: @@ -1200,7 +1208,7 @@ def create_execution( api_path = '/functions/{functionId}/executions' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) if body is not None: @@ -1256,9 +1264,9 @@ def get_execution( api_path = '/functions/{functionId}/executions/{executionId}' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') - if execution_id is None: + if execution_id is None or execution_id == '': raise AppwriteException('Missing required parameter: "execution_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) api_path = api_path.replace('{executionId}', str(self._normalize_value(execution_id))) @@ -1302,9 +1310,9 @@ def delete_execution( api_path = '/functions/{functionId}/executions/{executionId}' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') - if execution_id is None: + if execution_id is None or execution_id == '': raise AppwriteException('Missing required parameter: "execution_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) api_path = api_path.replace('{executionId}', str(self._normalize_value(execution_id))) @@ -1315,6 +1323,7 @@ def delete_execution( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -1351,7 +1360,7 @@ def list_variables( api_path = '/functions/{functionId}/variables' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) if queries is not None: @@ -1407,7 +1416,7 @@ def create_variable( api_path = '/functions/{functionId}/variables' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') if variable_id is None: raise AppwriteException('Missing required parameter: "variable_id"') @@ -1462,9 +1471,9 @@ def get_variable( api_path = '/functions/{functionId}/variables/{variableId}' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') - if variable_id is None: + if variable_id is None or variable_id == '': raise AppwriteException('Missing required parameter: "variable_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) api_path = api_path.replace('{variableId}', str(self._normalize_value(variable_id))) @@ -1517,9 +1526,9 @@ def update_variable( api_path = '/functions/{functionId}/variables/{variableId}' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') - if variable_id is None: + if variable_id is None or variable_id == '': raise AppwriteException('Missing required parameter: "variable_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) api_path = api_path.replace('{variableId}', str(self._normalize_value(variable_id))) @@ -1570,9 +1579,9 @@ def delete_variable( api_path = '/functions/{functionId}/variables/{variableId}' api_params = {} - if function_id is None: + if function_id is None or function_id == '': raise AppwriteException('Missing required parameter: "function_id"') - if variable_id is None: + if variable_id is None or variable_id == '': raise AppwriteException('Missing required parameter: "variable_id"') api_path = api_path.replace('{functionId}', str(self._normalize_value(function_id))) api_path = api_path.replace('{variableId}', str(self._normalize_value(variable_id))) @@ -1583,6 +1592,7 @@ def delete_variable( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) diff --git a/appwrite/services/messaging.py b/appwrite/services/messaging.py index 30368cd5..6b864262 100644 --- a/appwrite/services/messaging.py +++ b/appwrite/services/messaging.py @@ -33,7 +33,7 @@ def list_messages( Parameters ---------- queries : Optional[List[str]] - Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: scheduledAt, deliveredAt, deliveredTotal, status, description, providerType + Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: scheduledAt, deliveredAt, deliveredTotal, status, description, providerType, users, targets search : Optional[str] Search term to filter your list results. Max length: 256 chars. total : Optional[bool] @@ -241,7 +241,7 @@ def update_email( api_path = '/messaging/messages/email/{messageId}' api_params = {} - if message_id is None: + if message_id is None or message_id == '': raise AppwriteException('Missing required parameter: "message_id"') api_path = api_path.replace('{messageId}', str(self._normalize_value(message_id))) if topics is not None: @@ -501,7 +501,7 @@ def update_push( api_path = '/messaging/messages/push/{messageId}' api_params = {} - if message_id is None: + if message_id is None or message_id == '': raise AppwriteException('Missing required parameter: "message_id"') api_path = api_path.replace('{messageId}', str(self._normalize_value(message_id))) if topics is not None: @@ -670,7 +670,7 @@ def update_sms( api_path = '/messaging/messages/sms/{messageId}' api_params = {} - if message_id is None: + if message_id is None or message_id == '': raise AppwriteException('Missing required parameter: "message_id"') api_path = api_path.replace('{messageId}', str(self._normalize_value(message_id))) if topics is not None: @@ -723,7 +723,7 @@ def get_message( api_path = '/messaging/messages/{messageId}' api_params = {} - if message_id is None: + if message_id is None or message_id == '': raise AppwriteException('Missing required parameter: "message_id"') api_path = api_path.replace('{messageId}', str(self._normalize_value(message_id))) @@ -763,7 +763,7 @@ def delete( api_path = '/messaging/messages/{messageId}' api_params = {} - if message_id is None: + if message_id is None or message_id == '': raise AppwriteException('Missing required parameter: "message_id"') api_path = api_path.replace('{messageId}', str(self._normalize_value(message_id))) @@ -773,6 +773,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -809,7 +810,7 @@ def list_targets( api_path = '/messaging/messages/{messageId}/targets' api_params = {} - if message_id is None: + if message_id is None or message_id == '': raise AppwriteException('Missing required parameter: "message_id"') api_path = api_path.replace('{messageId}', str(self._normalize_value(message_id))) if queries is not None: @@ -1000,7 +1001,7 @@ def update_apns_provider( api_path = '/messaging/providers/apns/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) if name is not None: @@ -1053,7 +1054,7 @@ def create_appwrite_provider( qos : Optional[float] Default QoS for topics on this provider (0 or 1). Null lets the subscriber choose. expiry : Optional[float] - Default message retention in seconds for offline delivery. Max 7 days (604800). + Default message retention in seconds for offline delivery. Max 7 days (604800). Applies to topics with a null expiry; the lowest across enabled Appwrite providers wins. Returns ------- Provider @@ -1115,7 +1116,7 @@ def update_appwrite_provider( qos : Optional[float] Default QoS for topics on this provider (0 or 1). Null lets the subscriber choose. expiry : Optional[float] - Default message retention in seconds for offline delivery. Max 7 days (604800). + Default message retention in seconds for offline delivery. Max 7 days (604800). Applies to topics with a null expiry; the lowest across enabled Appwrite providers wins. Returns ------- Provider @@ -1244,7 +1245,7 @@ def update_fcm_provider( api_path = '/messaging/providers/fcm/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) if name is not None: @@ -1405,7 +1406,7 @@ def update_mailgun_provider( api_path = '/messaging/providers/mailgun/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) if name is not None: @@ -1546,7 +1547,7 @@ def update_msg91_provider( api_path = '/messaging/providers/msg91/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) if name is not None: @@ -1695,7 +1696,7 @@ def update_resend_provider( api_path = '/messaging/providers/resend/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) if name is not None: @@ -1848,7 +1849,7 @@ def update_sendgrid_provider( api_path = '/messaging/providers/sendgrid/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) if name is not None: @@ -2017,7 +2018,7 @@ def update_ses_provider( api_path = '/messaging/providers/ses/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) if name is not None: @@ -2223,7 +2224,7 @@ def update_smtp_provider( api_path = '/messaging/providers/smtp/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) if name is not None: @@ -2372,7 +2373,7 @@ def update_telesign_provider( api_path = '/messaging/providers/telesign/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) if name is not None: @@ -2505,7 +2506,7 @@ def update_textmagic_provider( api_path = '/messaging/providers/textmagic/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) if name is not None: @@ -2551,7 +2552,7 @@ def create_twilio_provider( name : str Provider name. xfrom : Optional[str] - Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212. + Sender phone number or alphanumeric sender ID. Format phone numbers with a leading '+' and a country code, e.g., +16175551212. account_sid : Optional[str] Twilio account secret ID. auth_token : Optional[str] @@ -2624,7 +2625,7 @@ def update_twilio_provider( auth_token : Optional[str] Twilio authentication token. xfrom : Optional[str] - Sender number. + Sender phone number or alphanumeric sender ID. Format phone numbers with a leading '+' and a country code, e.g., +16175551212. Returns ------- Provider @@ -2638,7 +2639,7 @@ def update_twilio_provider( api_path = '/messaging/providers/twilio/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) if name is not None: @@ -2771,7 +2772,7 @@ def update_vonage_provider( api_path = '/messaging/providers/vonage/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) if name is not None: @@ -2822,7 +2823,7 @@ def get_provider( api_path = '/messaging/providers/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) @@ -2862,7 +2863,7 @@ def delete_provider( api_path = '/messaging/providers/{providerId}' api_params = {} - if provider_id is None: + if provider_id is None or provider_id == '': raise AppwriteException('Missing required parameter: "provider_id"') api_path = api_path.replace('{providerId}', str(self._normalize_value(provider_id))) @@ -2872,6 +2873,7 @@ def delete_provider( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -2949,7 +2951,7 @@ def create_topic( qos : Optional[float] MQTT delivery quality of service for this topic. 0 is fire-and-forget (delivered only to clients connected at publish time). 1 persists each message and replays it when a client reconnects without having acknowledged it. Null lets the subscriber choose. expiry : Optional[float] - Message retention in seconds for offline delivery. Max 7 days (604800). + Message retention in seconds for offline delivery. Max 7 days (604800). Null inherits the lowest expiry of the project's enabled Appwrite providers, or the 7-day ledger window if none sets one. Returns ------- Topic @@ -3013,7 +3015,7 @@ def get_topic( api_path = '/messaging/topics/{topicId}' api_params = {} - if topic_id is None: + if topic_id is None or topic_id == '': raise AppwriteException('Missing required parameter: "topic_id"') api_path = api_path.replace('{topicId}', str(self._normalize_value(topic_id))) @@ -3051,7 +3053,7 @@ def update_topic( qos : Optional[float] MQTT delivery quality of service for this topic. 0 is fire-and-forget (delivered only to clients connected at publish time). 1 persists each message and replays it when a client reconnects without having acknowledged it. Null lets the subscriber choose. expiry : Optional[float] - Message retention in seconds for offline delivery. Max 7 days (604800). + Message retention in seconds for offline delivery. Max 7 days (604800). Null inherits the lowest expiry of the project's enabled Appwrite providers, or the 7-day ledger window if none sets one. Returns ------- Topic @@ -3065,7 +3067,7 @@ def update_topic( api_path = '/messaging/topics/{topicId}' api_params = {} - if topic_id is None: + if topic_id is None or topic_id == '': raise AppwriteException('Missing required parameter: "topic_id"') api_path = api_path.replace('{topicId}', str(self._normalize_value(topic_id))) if name is not None: @@ -3114,7 +3116,7 @@ def delete_topic( api_path = '/messaging/topics/{topicId}' api_params = {} - if topic_id is None: + if topic_id is None or topic_id == '': raise AppwriteException('Missing required parameter: "topic_id"') api_path = api_path.replace('{topicId}', str(self._normalize_value(topic_id))) @@ -3124,6 +3126,7 @@ def delete_topic( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -3163,7 +3166,7 @@ def list_subscribers( api_path = '/messaging/topics/{topicId}/subscribers' api_params = {} - if topic_id is None: + if topic_id is None or topic_id == '': raise AppwriteException('Missing required parameter: "topic_id"') api_path = api_path.replace('{topicId}', str(self._normalize_value(topic_id))) if queries is not None: @@ -3215,7 +3218,7 @@ def create_subscriber( api_path = '/messaging/topics/{topicId}/subscribers' api_params = {} - if topic_id is None: + if topic_id is None or topic_id == '': raise AppwriteException('Missing required parameter: "topic_id"') if subscriber_id is None: raise AppwriteException('Missing required parameter: "subscriber_id"') @@ -3265,9 +3268,9 @@ def get_subscriber( api_path = '/messaging/topics/{topicId}/subscribers/{subscriberId}' api_params = {} - if topic_id is None: + if topic_id is None or topic_id == '': raise AppwriteException('Missing required parameter: "topic_id"') - if subscriber_id is None: + if subscriber_id is None or subscriber_id == '': raise AppwriteException('Missing required parameter: "subscriber_id"') api_path = api_path.replace('{topicId}', str(self._normalize_value(topic_id))) api_path = api_path.replace('{subscriberId}', str(self._normalize_value(subscriber_id))) @@ -3311,9 +3314,9 @@ def delete_subscriber( api_path = '/messaging/topics/{topicId}/subscribers/{subscriberId}' api_params = {} - if topic_id is None: + if topic_id is None or topic_id == '': raise AppwriteException('Missing required parameter: "topic_id"') - if subscriber_id is None: + if subscriber_id is None or subscriber_id == '': raise AppwriteException('Missing required parameter: "subscriber_id"') api_path = api_path.replace('{topicId}', str(self._normalize_value(topic_id))) api_path = api_path.replace('{subscriberId}', str(self._normalize_value(subscriber_id))) @@ -3324,6 +3327,7 @@ def delete_subscriber( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) diff --git a/appwrite/services/mongo.py b/appwrite/services/mongo.py index 4fb19898..7bb92df1 100644 --- a/appwrite/services/mongo.py +++ b/appwrite/services/mongo.py @@ -114,7 +114,7 @@ def create( storage_autoscaling_threshold_percent : Optional[float] Storage usage percentage (50-95) that triggers automatic expansion. storage_autoscaling_max_gb : Optional[float] - Maximum storage size in GB for autoscaling. 0 means no limit. + Maximum storage size in GB for autoscaling. Defaults to 3 times the specification's storage. 0 means no limit. Returns ------- DedicatedDatabase @@ -178,7 +178,7 @@ def list_specifications( self, ) -> DedicatedDatabaseSpecificationList: """ - List the dedicated database specifications available on the current plan. Each specification reports its resource limits, pricing, and whether it is enabled for the organization. + List the dedicated database specifications available on the current plan. Each specification reports its resource limits, its own prices and overage rates, and whether it is enabled for the organization. Returns ------- DedicatedDatabaseSpecificationList @@ -229,7 +229,7 @@ def get( api_path = '/mongo/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -329,7 +329,7 @@ def update( api_path = '/mongo/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if name is not None: @@ -412,7 +412,7 @@ def delete( api_path = '/mongo/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -456,7 +456,7 @@ def list_backups( api_path = '/mongo/{databaseId}/backups' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if queries is not None: @@ -501,7 +501,7 @@ def create_backup( api_path = '/mongo/{databaseId}/backups' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if type is not None: @@ -547,7 +547,7 @@ def list_backup_policies( api_path = '/mongo/{databaseId}/backups/policies' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if queries is not None: @@ -607,7 +607,7 @@ def create_backup_policy( api_path = '/mongo/{databaseId}/backups/policies' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if policy_id is None: raise AppwriteException('Missing required parameter: "policy_id"') @@ -667,9 +667,9 @@ def get_backup_policy( api_path = '/mongo/{databaseId}/backups/policies/{policyId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if policy_id is None: + if policy_id is None or policy_id == '': raise AppwriteException('Missing required parameter: "policy_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{policyId}', str(self._normalize_value(policy_id))) @@ -725,9 +725,9 @@ def update_backup_policy( api_path = '/mongo/{databaseId}/backups/policies/{policyId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if policy_id is None: + if policy_id is None or policy_id == '': raise AppwriteException('Missing required parameter: "policy_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{policyId}', str(self._normalize_value(policy_id))) @@ -780,9 +780,9 @@ def delete_backup_policy( api_path = '/mongo/{databaseId}/backups/policies/{policyId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if policy_id is None: + if policy_id is None or policy_id == '': raise AppwriteException('Missing required parameter: "policy_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{policyId}', str(self._normalize_value(policy_id))) @@ -845,7 +845,7 @@ def update_backup_storage( api_path = '/mongo/{databaseId}/backups/storage' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if provider is None: raise AppwriteException('Missing required parameter: "provider"') @@ -907,9 +907,9 @@ def get_backup( api_path = '/mongo/{databaseId}/backups/{backupId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if backup_id is None: + if backup_id is None or backup_id == '': raise AppwriteException('Missing required parameter: "backup_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{backupId}', str(self._normalize_value(backup_id))) @@ -953,9 +953,9 @@ def delete_backup( api_path = '/mongo/{databaseId}/backups/{backupId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if backup_id is None: + if backup_id is None or backup_id == '': raise AppwriteException('Missing required parameter: "backup_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{backupId}', str(self._normalize_value(backup_id))) @@ -997,7 +997,7 @@ def list_branches( api_path = '/mongo/{databaseId}/branches' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1043,7 +1043,7 @@ def create_branch( api_path = '/mongo/{databaseId}/branches' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if branch_id is not None: @@ -1091,9 +1091,9 @@ def delete_branch( api_path = '/mongo/{databaseId}/branches/{branchId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if branch_id is None: + if branch_id is None or branch_id == '': raise AppwriteException('Missing required parameter: "branch_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{branchId}', str(self._normalize_value(branch_id))) @@ -1135,7 +1135,7 @@ def update_credentials( api_path = '/mongo/{databaseId}/credentials' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1179,7 +1179,7 @@ def create_failover( api_path = '/mongo/{databaseId}/failovers' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if target_replica_id is not None: @@ -1228,7 +1228,7 @@ def update_maintenance( api_path = '/mongo/{databaseId}/maintenance' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if day is None: raise AppwriteException('Missing required parameter: "day"') @@ -1281,7 +1281,7 @@ def create_migration( api_path = '/mongo/{databaseId}/migrations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if target_type is None: raise AppwriteException('Missing required parameter: "target_type"') @@ -1336,7 +1336,7 @@ def list_operations( api_path = '/mongo/{databaseId}/operations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if status is not None: @@ -1382,7 +1382,7 @@ def get_pitr( api_path = '/mongo/{databaseId}/pitr' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1422,7 +1422,7 @@ def get_replicas( api_path = '/mongo/{databaseId}/replicas' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1474,7 +1474,7 @@ def list_restorations( api_path = '/mongo/{databaseId}/restorations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if status is not None: @@ -1505,10 +1505,15 @@ def create_restoration( backup_id: Optional[str] = None, target_database_id: Optional[str] = None, target_time: Optional[str] = None, + restore_mode: Optional[str] = None, + target_name: Optional[str] = None, + auto_promote: Optional[bool] = None, ) -> DedicatedDatabaseRestoration: """ Restore a database from a backup or to a specific point in time (PITR). For backup restoration, provide a backupId. For PITR, provide a targetTime as an ISO 8601 datetime. PITR requires the database to have PITR enabled and is only available for enterprise databases. + By default the backup is replayed over the database it was taken from. Pass `restoreMode` as `clone` to recover it onto a second workload beside this database instead: this database keeps serving its own data while the clone is filled, and the switch happens as soon as the clone is ready, on the endpoint and credentials it already had. Pass `autoPromote` as false to hold the clone until you promote it yourself. Pass `restoreMode` as `copy` to recover onto a separate database with its own endpoint, either one you name with `targetDatabaseId` or one provisioned as a copy of this database's engine, version, specification and replicas. Neither mode is available for a point-in-time recovery or an incremental backup. + Parameters ---------- database_id : str @@ -1518,9 +1523,15 @@ def create_restoration( backup_id : Optional[str] Backup ID to restore from (required for backup type). target_database_id : Optional[str] - Existing database ID to restore into. The target must be distinct, ready, and use the same engine and version. + Existing database ID to restore into. The target must be distinct, ready, and use the same engine and version. Omit it on a copy restoration to have one provisioned. Not accepted for a clone, which is recovered inside this database. target_time : Optional[str] Target time for PITR (required for pitr type) as an [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) datetime. + restore_mode : Optional[str] + Where the backup is restored. Allowed values: in_place, clone, copy. Use "clone" to recover onto a second workload beside this database and leave it serving until you promote — the endpoint and credentials do not change. Use "copy" to recover onto a separate database with its own endpoint, either one you name with targetDatabaseId or one Cloud provisions. Use "in_place" to replay the backup over this database. Defaults to "copy" when a targetDatabaseId is given, "in_place" otherwise. + target_name : Optional[str] + Display name for the database a copy restoration provisions. Defaults to this database's name followed by "(restored)". Max length: 128 chars. + auto_promote : Optional[bool] + Whether a clone restoration switches the database over as soon as the recovery is ready. Default true: the restore finishes with the database serving the recovery point on the endpoint it already had, and the side it replaced kept briefly so the switch can be reversed. Pass false to hold the recovery until you call the promotion endpoint yourself. Returns ------- DedicatedDatabaseRestoration @@ -1534,7 +1545,7 @@ def create_restoration( api_path = '/mongo/{databaseId}/restorations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if type is not None: @@ -1545,6 +1556,12 @@ def create_restoration( api_params['targetDatabaseId'] = self._normalize_value(target_database_id) if target_time is not None: api_params['targetTime'] = self._normalize_value(target_time) + if restore_mode is not None: + api_params['restoreMode'] = self._normalize_value(restore_mode) + if target_name is not None: + api_params['targetName'] = self._normalize_value(target_name) + if auto_promote is not None: + api_params['autoPromote'] = self._normalize_value(auto_promote) response = self.client.call( 'post', @@ -1586,9 +1603,9 @@ def get_restoration( api_path = '/mongo/{databaseId}/restorations/{restorationId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if restoration_id is None: + if restoration_id is None or restoration_id == '': raise AppwriteException('Missing required parameter: "restoration_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{restorationId}', str(self._normalize_value(restoration_id))) @@ -1605,6 +1622,56 @@ def get_restoration( return self._parse_response(response, model=DedicatedDatabaseRestoration) + def promote_restoration( + self, + database_id: str, + restoration_id: str, + ) -> DedicatedDatabaseRestoration: + """ + Switch the database over to the clone a restoration recovered. The database keeps + its endpoint and credentials; clients reconnect once. Writes made after the + recovery point are discarded, and the side being replaced is retained briefly so + the switch can be reversed. + + Parameters + ---------- + database_id : str + Database ID. + restoration_id : str + Restoration ID. + Returns + ------- + DedicatedDatabaseRestoration + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/mongo/{databaseId}/restorations/{restorationId}/promotions' + api_params = {} + if database_id is None or database_id == '': + raise AppwriteException('Missing required parameter: "database_id"') + if restoration_id is None or restoration_id == '': + raise AppwriteException('Missing required parameter: "restoration_id"') + api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) + api_path = api_path.replace('{restorationId}', str(self._normalize_value(restoration_id))) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DedicatedDatabaseRestoration) + def get_status( self, database_id: str, @@ -1629,7 +1696,7 @@ def get_status( api_path = '/mongo/{databaseId}/status' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1672,7 +1739,7 @@ def create_upgrade( api_path = '/mongo/{databaseId}/upgrades' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if target_version is None: raise AppwriteException('Missing required parameter: "target_version"') diff --git a/appwrite/services/mysql.py b/appwrite/services/mysql.py index a40b04c1..4e70e83f 100644 --- a/appwrite/services/mysql.py +++ b/appwrite/services/mysql.py @@ -116,7 +116,7 @@ def create( storage_autoscaling_threshold_percent : Optional[float] Storage usage percentage (50-95) that triggers automatic expansion. storage_autoscaling_max_gb : Optional[float] - Maximum storage size in GB for autoscaling. 0 means no limit. + Maximum storage size in GB for autoscaling. Defaults to 3 times the specification's storage. 0 means no limit. Returns ------- DedicatedDatabase @@ -180,7 +180,7 @@ def list_specifications( self, ) -> DedicatedDatabaseSpecificationList: """ - List the dedicated database specifications available on the current plan. Each specification reports its resource limits, pricing, and whether it is enabled for the organization. + List the dedicated database specifications available on the current plan. Each specification reports its resource limits, its own prices and overage rates, and whether it is enabled for the organization. Returns ------- DedicatedDatabaseSpecificationList @@ -231,7 +231,7 @@ def get( api_path = '/mysql/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -331,7 +331,7 @@ def update( api_path = '/mysql/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if name is not None: @@ -414,7 +414,7 @@ def delete( api_path = '/mysql/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -458,7 +458,7 @@ def list_backups( api_path = '/mysql/{databaseId}/backups' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if queries is not None: @@ -503,7 +503,7 @@ def create_backup( api_path = '/mysql/{databaseId}/backups' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if type is not None: @@ -549,7 +549,7 @@ def list_backup_policies( api_path = '/mysql/{databaseId}/backups/policies' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if queries is not None: @@ -609,7 +609,7 @@ def create_backup_policy( api_path = '/mysql/{databaseId}/backups/policies' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if policy_id is None: raise AppwriteException('Missing required parameter: "policy_id"') @@ -669,9 +669,9 @@ def get_backup_policy( api_path = '/mysql/{databaseId}/backups/policies/{policyId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if policy_id is None: + if policy_id is None or policy_id == '': raise AppwriteException('Missing required parameter: "policy_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{policyId}', str(self._normalize_value(policy_id))) @@ -727,9 +727,9 @@ def update_backup_policy( api_path = '/mysql/{databaseId}/backups/policies/{policyId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if policy_id is None: + if policy_id is None or policy_id == '': raise AppwriteException('Missing required parameter: "policy_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{policyId}', str(self._normalize_value(policy_id))) @@ -782,9 +782,9 @@ def delete_backup_policy( api_path = '/mysql/{databaseId}/backups/policies/{policyId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if policy_id is None: + if policy_id is None or policy_id == '': raise AppwriteException('Missing required parameter: "policy_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{policyId}', str(self._normalize_value(policy_id))) @@ -847,7 +847,7 @@ def update_backup_storage( api_path = '/mysql/{databaseId}/backups/storage' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if provider is None: raise AppwriteException('Missing required parameter: "provider"') @@ -909,9 +909,9 @@ def get_backup( api_path = '/mysql/{databaseId}/backups/{backupId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if backup_id is None: + if backup_id is None or backup_id == '': raise AppwriteException('Missing required parameter: "backup_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{backupId}', str(self._normalize_value(backup_id))) @@ -955,9 +955,9 @@ def delete_backup( api_path = '/mysql/{databaseId}/backups/{backupId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if backup_id is None: + if backup_id is None or backup_id == '': raise AppwriteException('Missing required parameter: "backup_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{backupId}', str(self._normalize_value(backup_id))) @@ -999,7 +999,7 @@ def list_branches( api_path = '/mysql/{databaseId}/branches' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1045,7 +1045,7 @@ def create_branch( api_path = '/mysql/{databaseId}/branches' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if branch_id is not None: @@ -1093,9 +1093,9 @@ def delete_branch( api_path = '/mysql/{databaseId}/branches/{branchId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if branch_id is None: + if branch_id is None or branch_id == '': raise AppwriteException('Missing required parameter: "branch_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{branchId}', str(self._normalize_value(branch_id))) @@ -1137,7 +1137,7 @@ def update_credentials( api_path = '/mysql/{databaseId}/credentials' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1162,7 +1162,7 @@ def create_execution( timeout_seconds: Optional[float] = None, ) -> DedicatedDatabaseExecution: """ - Execute SQL through the console-facing Cloud endpoint. Cloud proxies through the edge platform to the per-database SQL API sidecar. Application traffic should bypass cloud entirely and POST directly to the per-database hostname: `https://db-{project}-{db}.{region}.appwrite.center/v1/sql/executions` with an `X-Appwrite-Key` header — that path scales to the whole DB fleet without a per-query cloud round-trip. The statement type must be on the database's configured allow-list. Use bound parameters for any user-supplied values — the API does not interpolate raw strings. + Execute SQL through the console-facing Cloud endpoint. Cloud proxies through the edge platform to the per-database SQL API sidecar. Application traffic should bypass cloud entirely and POST directly to the per-database hostname: `https://db-{project}-{db}.{region}.appwrite.center/v1/sql/executions` with an `X-Appwrite-Key` header — that path scales to the whole DB fleet without a per-query cloud round-trip. The statement type must be on the database's configured allow-list. Use bound parameters for any user-supplied values — the API does not interpolate raw strings. Long-running statements (for example CREATE INDEX) can outlive the HTTP request: if the request ends before a result is returned, check the database before retrying, and prefer a direct connection for work that may take minutes. Parameters ---------- @@ -1173,7 +1173,7 @@ def create_execution( bindings : Optional[Dict[str, Any]] Optional bound parameters. Pass either a positional list or a name => value map matching the placeholder style used in the SQL. timeout_seconds : Optional[float] - Per-call execution timeout override. Must be less than or equal to the database's configured sqlApiTimeoutSeconds. + Per-call execution timeout override. Must be less than or equal to the database's configured sqlApiTimeoutSeconds. Statements that may exceed this — or the HTTP request timeout in front of Cloud — should use a direct connection instead. Returns ------- DedicatedDatabaseExecution @@ -1187,7 +1187,7 @@ def create_execution( api_path = '/mysql/{databaseId}/executions' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if sql is None: raise AppwriteException('Missing required parameter: "sql"') @@ -1238,7 +1238,7 @@ def create_failover( api_path = '/mysql/{databaseId}/failovers' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if target_replica_id is not None: @@ -1287,7 +1287,7 @@ def update_maintenance( api_path = '/mysql/{databaseId}/maintenance' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if day is None: raise AppwriteException('Missing required parameter: "day"') @@ -1340,7 +1340,7 @@ def create_migration( api_path = '/mysql/{databaseId}/migrations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if target_type is None: raise AppwriteException('Missing required parameter: "target_type"') @@ -1395,7 +1395,7 @@ def list_operations( api_path = '/mysql/{databaseId}/operations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if status is not None: @@ -1441,7 +1441,7 @@ def get_pitr( api_path = '/mysql/{databaseId}/pitr' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1481,7 +1481,7 @@ def get_pooler( api_path = '/mysql/{databaseId}/pooler' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1523,7 +1523,7 @@ def update_pooler( default_pool_size : Optional[float] Default pool size per user. read_write_splitting : Optional[bool] - Route SELECTs to HA replicas, writes and locked reads to the primary. Defaults to true when HA is enabled. + Route SELECTs to HA replicas, writes and locked reads to the primary. Off by default, and only takes effect while HA is enabled. Replication is asynchronous, so a read issued immediately after a write may not observe it. pooler_cpu_request : Optional[str] Pooler sidecar CPU request override (Kubernetes quantity, e.g. "250m" or "1"). Leave null for the proportional default (5% of DB CPU, floor 100m). pooler_cpu_limit : Optional[str] @@ -1545,7 +1545,7 @@ def update_pooler( api_path = '/mysql/{databaseId}/pooler' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if mode is not None: @@ -1602,7 +1602,7 @@ def get_replicas( api_path = '/mysql/{databaseId}/replicas' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1654,7 +1654,7 @@ def list_restorations( api_path = '/mysql/{databaseId}/restorations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if status is not None: @@ -1685,10 +1685,15 @@ def create_restoration( backup_id: Optional[str] = None, target_database_id: Optional[str] = None, target_time: Optional[str] = None, + restore_mode: Optional[str] = None, + target_name: Optional[str] = None, + auto_promote: Optional[bool] = None, ) -> DedicatedDatabaseRestoration: """ Restore a database from a backup or to a specific point in time (PITR). For backup restoration, provide a backupId. For PITR, provide a targetTime as an ISO 8601 datetime. PITR requires the database to have PITR enabled and is only available for enterprise databases. + By default the backup is replayed over the database it was taken from. Pass `restoreMode` as `clone` to recover it onto a second workload beside this database instead: this database keeps serving its own data while the clone is filled, and the switch happens as soon as the clone is ready, on the endpoint and credentials it already had. Pass `autoPromote` as false to hold the clone until you promote it yourself. Pass `restoreMode` as `copy` to recover onto a separate database with its own endpoint, either one you name with `targetDatabaseId` or one provisioned as a copy of this database's engine, version, specification and replicas. Neither mode is available for a point-in-time recovery or an incremental backup. + Parameters ---------- database_id : str @@ -1698,9 +1703,15 @@ def create_restoration( backup_id : Optional[str] Backup ID to restore from (required for backup type). target_database_id : Optional[str] - Existing database ID to restore into. The target must be distinct, ready, and use the same engine and version. + Existing database ID to restore into. The target must be distinct, ready, and use the same engine and version. Omit it on a copy restoration to have one provisioned. Not accepted for a clone, which is recovered inside this database. target_time : Optional[str] Target time for PITR (required for pitr type) as an [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) datetime. + restore_mode : Optional[str] + Where the backup is restored. Allowed values: in_place, clone, copy. Use "clone" to recover onto a second workload beside this database and leave it serving until you promote — the endpoint and credentials do not change. Use "copy" to recover onto a separate database with its own endpoint, either one you name with targetDatabaseId or one Cloud provisions. Use "in_place" to replay the backup over this database. Defaults to "copy" when a targetDatabaseId is given, "in_place" otherwise. + target_name : Optional[str] + Display name for the database a copy restoration provisions. Defaults to this database's name followed by "(restored)". Max length: 128 chars. + auto_promote : Optional[bool] + Whether a clone restoration switches the database over as soon as the recovery is ready. Default true: the restore finishes with the database serving the recovery point on the endpoint it already had, and the side it replaced kept briefly so the switch can be reversed. Pass false to hold the recovery until you call the promotion endpoint yourself. Returns ------- DedicatedDatabaseRestoration @@ -1714,7 +1725,7 @@ def create_restoration( api_path = '/mysql/{databaseId}/restorations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if type is not None: @@ -1725,6 +1736,12 @@ def create_restoration( api_params['targetDatabaseId'] = self._normalize_value(target_database_id) if target_time is not None: api_params['targetTime'] = self._normalize_value(target_time) + if restore_mode is not None: + api_params['restoreMode'] = self._normalize_value(restore_mode) + if target_name is not None: + api_params['targetName'] = self._normalize_value(target_name) + if auto_promote is not None: + api_params['autoPromote'] = self._normalize_value(auto_promote) response = self.client.call( 'post', @@ -1766,9 +1783,9 @@ def get_restoration( api_path = '/mysql/{databaseId}/restorations/{restorationId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if restoration_id is None: + if restoration_id is None or restoration_id == '': raise AppwriteException('Missing required parameter: "restoration_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{restorationId}', str(self._normalize_value(restoration_id))) @@ -1785,6 +1802,56 @@ def get_restoration( return self._parse_response(response, model=DedicatedDatabaseRestoration) + def promote_restoration( + self, + database_id: str, + restoration_id: str, + ) -> DedicatedDatabaseRestoration: + """ + Switch the database over to the clone a restoration recovered. The database keeps + its endpoint and credentials; clients reconnect once. Writes made after the + recovery point are discarded, and the side being replaced is retained briefly so + the switch can be reversed. + + Parameters + ---------- + database_id : str + Database ID. + restoration_id : str + Restoration ID. + Returns + ------- + DedicatedDatabaseRestoration + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/mysql/{databaseId}/restorations/{restorationId}/promotions' + api_params = {} + if database_id is None or database_id == '': + raise AppwriteException('Missing required parameter: "database_id"') + if restoration_id is None or restoration_id == '': + raise AppwriteException('Missing required parameter: "restoration_id"') + api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) + api_path = api_path.replace('{restorationId}', str(self._normalize_value(restoration_id))) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DedicatedDatabaseRestoration) + def get_status( self, database_id: str, @@ -1809,7 +1876,7 @@ def get_status( api_path = '/mysql/{databaseId}/status' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1852,7 +1919,7 @@ def create_upgrade( api_path = '/mysql/{databaseId}/upgrades' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if target_version is None: raise AppwriteException('Missing required parameter: "target_version"') diff --git a/appwrite/services/oauth2.py b/appwrite/services/oauth2.py index de59e3e8..774dcf2c 100644 --- a/appwrite/services/oauth2.py +++ b/appwrite/services/oauth2.py @@ -84,7 +84,7 @@ def authorize( prompt: Optional[str] = None, max_age: Optional[float] = None, authorization_details: Optional[str] = None, - resource: Optional[str] = None, + resource: Optional[List[str]] = None, audience: Optional[str] = None, request_uri: Optional[str] = None, ) -> Oauth2Authorize: @@ -115,7 +115,7 @@ def authorize( OIDC max_age paraleter for customization of consent screen. Maximum allowable elapsed time in seconds since the user last authenticated. If exceeded, re-authentication is required. authorization_details : Optional[str] Rich authorization request. JSON array of objects, each with a `type` and project-defined fields - resource : Optional[str] + resource : Optional[List[str]] RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. audience : Optional[str] Compatibility alias for a single OAuth2 resource indicator URI. @@ -188,7 +188,7 @@ def authorize_post( prompt: Optional[str] = None, max_age: Optional[float] = None, authorization_details: Optional[str] = None, - resource: Optional[str] = None, + resource: Optional[List[str]] = None, audience: Optional[str] = None, request_uri: Optional[str] = None, ) -> Oauth2Authorize: @@ -219,7 +219,7 @@ def authorize_post( OIDC max_age paraleter for customization of consent screen. Maximum allowable elapsed time in seconds since the user last authenticated. If exceeded, re-authentication is required. authorization_details : Optional[str] Rich authorization request. JSON array of objects, each with a `type` and project-defined fields - resource : Optional[str] + resource : Optional[List[str]] RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. audience : Optional[str] Compatibility alias for a single OAuth2 resource indicator URI. @@ -285,7 +285,7 @@ def create_device_authorization( client_id: Optional[str] = None, scope: Optional[str] = None, authorization_details: Optional[str] = None, - resource: Optional[str] = None, + resource: Optional[List[str]] = None, audience: Optional[str] = None, ) -> Oauth2DeviceAuthorization: """ @@ -299,7 +299,7 @@ def create_device_authorization( Space-separated OAuth2 scopes. Can include project scopes, and built-in scopes: `openid`, `email`, `profile`. authorization_details : Optional[str] Rich authorization request. JSON array of objects, each with a `type` and project-defined fields - resource : Optional[str] + resource : Optional[List[str]] RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. audience : Optional[str] Compatibility alias for a single OAuth2 resource indicator URI. @@ -405,7 +405,7 @@ def get_grant( api_path = '/oauth2/{project_id}/grants/{grant_id}' api_params = {} - if grant_id is None: + if grant_id is None or grant_id == '': raise AppwriteException('Missing required parameter: "grant_id"') api_path = api_path.replace('{project_id}', str(self._normalize_value(self.client.get_config('project')))) api_path = api_path.replace('{grant_id}', str(self._normalize_value(grant_id))) @@ -539,7 +539,7 @@ def create_par( prompt: Optional[str] = None, max_age: Optional[float] = None, authorization_details: Optional[str] = None, - resource: Optional[str] = None, + resource: Optional[List[str]] = None, audience: Optional[str] = None, ) -> Oauth2PAR: """ @@ -569,7 +569,7 @@ def create_par( OIDC max_age parameter for customization of consent screen. authorization_details : Optional[str] Rich authorization request. JSON array of objects, each with a `type` and project-defined fields - resource : Optional[str] + resource : Optional[List[str]] RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. audience : Optional[str] Compatibility alias for a single OAuth2 resource indicator URI. @@ -785,7 +785,7 @@ def create_token( client_secret: Optional[str] = None, code_verifier: Optional[str] = None, redirect_uri: Optional[str] = None, - resource: Optional[str] = None, + resource: Optional[List[str]] = None, audience: Optional[str] = None, ) -> Oauth2Token: """ @@ -809,7 +809,7 @@ def create_token( PKCE code verifier. Required for public apps. redirect_uri : Optional[str] Redirect URI. Required for `authorization_code` grant type. - resource : Optional[str] + resource : Optional[List[str]] RFC 8707 resource indicator URI or URI list. Each value must be an absolute URI without a fragment. audience : Optional[str] Compatibility alias for a single OAuth2 resource indicator URI. diff --git a/appwrite/services/organization.py b/appwrite/services/organization.py index 0c9e73f6..0e31be2b 100644 --- a/appwrite/services/organization.py +++ b/appwrite/services/organization.py @@ -6,9 +6,6 @@ from ..models.organization import Organization as OrganizationModel from ..models.app_installation_list import AppInstallationList from ..models.app_installation import AppInstallation -from ..models.key_list import KeyList -from ..enums.organization_key_scopes import OrganizationKeyScopes -from ..models.key import Key from ..models.membership_list import MembershipList from ..models.membership import Membership from ..models.project_list import ProjectList @@ -135,6 +132,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -255,7 +253,7 @@ def get_installation( api_path = '/organization/installations/{installationId}' api_params = {} - if installation_id is None: + if installation_id is None or installation_id == '': raise AppwriteException('Missing required parameter: "installation_id"') api_path = api_path.replace('{installationId}', str(self._normalize_value(installation_id))) @@ -298,7 +296,7 @@ def update_installation( api_path = '/organization/installations/{installationId}' api_params = {} - if installation_id is None: + if installation_id is None or installation_id == '': raise AppwriteException('Missing required parameter: "installation_id"') api_path = api_path.replace('{installationId}', str(self._normalize_value(installation_id))) if authorization_details is not None: @@ -341,7 +339,7 @@ def delete_installation( api_path = '/organization/installations/{installationId}' api_params = {} - if installation_id is None: + if installation_id is None or installation_id == '': raise AppwriteException('Missing required parameter: "installation_id"') api_path = api_path.replace('{installationId}', str(self._normalize_value(installation_id))) @@ -358,246 +356,6 @@ def delete_installation( return response - def list_keys( - self, - queries: Optional[List[str]] = None, - total: Optional[bool] = None, - ) -> KeyList: - """ - Get a list of all API keys from the current organization. - - Parameters - ---------- - queries : Optional[List[str]] - Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: expire, accessedAt, name, scopes - total : Optional[bool] - When set to false, the total count returned will be 0 and will not be calculated. - Returns - ------- - KeyList - API response as a typed Pydantic model - - Raises - ------ - AppwriteException - If API request fails - """ - - api_path = '/organization/keys' - api_params = {} - if queries is not None: - api_params['queries'] = self._normalize_value(queries) - if total is not None: - api_params['total'] = self._normalize_value(total) - - response = self.client.call( - 'get', - api_path, - { - 'X-Appwrite-Project': self.client.get_config('project'), - 'accept': 'application/json', - }, - api_params, - ) - - return self._parse_response(response, model=KeyList) - - def create_key( - self, - key_id: str, - name: str, - scopes: List[OrganizationKeyScopes], - expire: Optional[str] = None, - ) -> Key: - """ - Create a new organization API key. - - Parameters - ---------- - key_id : str - Key ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars. - name : str - Key name. Max length: 128 chars. - scopes : List[OrganizationKeyScopes] - Key scopes list. Maximum of 200 scopes are allowed. - expire : Optional[str] - Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration. - Returns - ------- - Key - API response as a typed Pydantic model - - Raises - ------ - AppwriteException - If API request fails - """ - - api_path = '/organization/keys' - api_params = {} - if key_id is None: - raise AppwriteException('Missing required parameter: "key_id"') - if name is None: - raise AppwriteException('Missing required parameter: "name"') - if scopes is None: - raise AppwriteException('Missing required parameter: "scopes"') - api_params['keyId'] = self._normalize_value(key_id) - api_params['name'] = self._normalize_value(name) - api_params['scopes'] = self._normalize_value(scopes) - if expire is not None: - api_params['expire'] = self._normalize_value(expire) - - response = self.client.call( - 'post', - api_path, - { - 'X-Appwrite-Project': self.client.get_config('project'), - 'content-type': 'application/json', - 'accept': 'application/json', - }, - api_params, - ) - - return self._parse_response(response, model=Key) - - def get_key( - self, - key_id: str, - ) -> Key: - """ - Get a key by its unique ID. This endpoint returns details about a specific API key in your organization including its scopes. - - Parameters - ---------- - key_id : str - Key unique ID. - Returns - ------- - Key - API response as a typed Pydantic model - - Raises - ------ - AppwriteException - If API request fails - """ - - api_path = '/organization/keys/{keyId}' - api_params = {} - if key_id is None: - raise AppwriteException('Missing required parameter: "key_id"') - api_path = api_path.replace('{keyId}', str(self._normalize_value(key_id))) - - response = self.client.call( - 'get', - api_path, - { - 'X-Appwrite-Project': self.client.get_config('project'), - 'accept': 'application/json', - }, - api_params, - ) - - return self._parse_response(response, model=Key) - - def update_key( - self, - key_id: str, - name: str, - scopes: List[OrganizationKeyScopes], - expire: Optional[str] = None, - ) -> Key: - """ - Update a key by its unique ID. Use this endpoint to update the name, scopes, or expiration time of an API key. - - Parameters - ---------- - key_id : str - Key unique ID. - name : str - Key name. Max length: 128 chars. - scopes : List[OrganizationKeyScopes] - Key scopes list. Maximum of 200 scopes are allowed. - expire : Optional[str] - Expiration time in [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration. - Returns - ------- - Key - API response as a typed Pydantic model - - Raises - ------ - AppwriteException - If API request fails - """ - - api_path = '/organization/keys/{keyId}' - api_params = {} - if key_id is None: - raise AppwriteException('Missing required parameter: "key_id"') - if name is None: - raise AppwriteException('Missing required parameter: "name"') - if scopes is None: - raise AppwriteException('Missing required parameter: "scopes"') - api_path = api_path.replace('{keyId}', str(self._normalize_value(key_id))) - api_params['name'] = self._normalize_value(name) - api_params['scopes'] = self._normalize_value(scopes) - if expire is not None: - api_params['expire'] = self._normalize_value(expire) - - response = self.client.call( - 'put', - api_path, - { - 'X-Appwrite-Project': self.client.get_config('project'), - 'content-type': 'application/json', - 'accept': 'application/json', - }, - api_params, - ) - - return self._parse_response(response, model=Key) - - def delete_key( - self, - key_id: str, - ) -> Dict[str, Any]: - """ - Delete a key by its unique ID. Once deleted, the key can no longer be used to authenticate API calls. - - Parameters - ---------- - key_id : str - Key unique ID. - Returns - ------- - Dict[str, Any] - API response as a dictionary - - Raises - ------ - AppwriteException - If API request fails - """ - - api_path = '/organization/keys/{keyId}' - api_params = {} - if key_id is None: - raise AppwriteException('Missing required parameter: "key_id"') - api_path = api_path.replace('{keyId}', str(self._normalize_value(key_id))) - - response = self.client.call( - 'delete', - api_path, - { - 'X-Appwrite-Project': self.client.get_config('project'), - 'content-type': 'application/json', - }, - api_params, - ) - - return response - def list_memberships( self, queries: Optional[List[str]] = None, @@ -737,7 +495,7 @@ def get_membership( api_path = '/organization/memberships/{membershipId}' api_params = {} - if membership_id is None: + if membership_id is None or membership_id == '': raise AppwriteException('Missing required parameter: "membership_id"') api_path = api_path.replace('{membershipId}', str(self._normalize_value(membership_id))) @@ -780,7 +538,7 @@ def update_membership( api_path = '/organization/memberships/{membershipId}' api_params = {} - if membership_id is None: + if membership_id is None or membership_id == '': raise AppwriteException('Missing required parameter: "membership_id"') if roles is None: raise AppwriteException('Missing required parameter: "roles"') @@ -824,7 +582,7 @@ def delete_membership( api_path = '/organization/memberships/{membershipId}' api_params = {} - if membership_id is None: + if membership_id is None or membership_id == '': raise AppwriteException('Missing required parameter: "membership_id"') api_path = api_path.replace('{membershipId}', str(self._normalize_value(membership_id))) @@ -834,6 +592,7 @@ def delete_membership( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -965,7 +724,7 @@ def get_project( api_path = '/organization/projects/{projectId}' api_params = {} - if project_id is None: + if project_id is None or project_id == '': raise AppwriteException('Missing required parameter: "project_id"') api_path = api_path.replace('{projectId}', str(self._normalize_value(project_id))) @@ -974,6 +733,7 @@ def get_project( api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params, ) @@ -1007,7 +767,7 @@ def update_project( api_path = '/organization/projects/{projectId}' api_params = {} - if project_id is None: + if project_id is None or project_id == '': raise AppwriteException('Missing required parameter: "project_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -1051,7 +811,7 @@ def delete_project( api_path = '/organization/projects/{projectId}' api_params = {} - if project_id is None: + if project_id is None or project_id == '': raise AppwriteException('Missing required parameter: "project_id"') api_path = api_path.replace('{projectId}', str(self._normalize_value(project_id))) @@ -1061,6 +821,7 @@ def delete_project( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) diff --git a/appwrite/services/postgresql.py b/appwrite/services/postgresql.py index 19d1ff74..f361d9dd 100644 --- a/appwrite/services/postgresql.py +++ b/appwrite/services/postgresql.py @@ -117,7 +117,7 @@ def create( storage_autoscaling_threshold_percent : Optional[float] Storage usage percentage (50-95) that triggers automatic expansion. storage_autoscaling_max_gb : Optional[float] - Maximum storage size in GB for autoscaling. 0 means no limit. + Maximum storage size in GB for autoscaling. Defaults to 3 times the specification's storage. 0 means no limit. Returns ------- DedicatedDatabase @@ -181,7 +181,7 @@ def list_specifications( self, ) -> DedicatedDatabaseSpecificationList: """ - List the dedicated database specifications available on the current plan. Each specification reports its resource limits, pricing, and whether it is enabled for the organization. + List the dedicated database specifications available on the current plan. Each specification reports its resource limits, its own prices and overage rates, and whether it is enabled for the organization. Returns ------- DedicatedDatabaseSpecificationList @@ -232,7 +232,7 @@ def get( api_path = '/postgresql/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -332,7 +332,7 @@ def update( api_path = '/postgresql/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if name is not None: @@ -415,7 +415,7 @@ def delete( api_path = '/postgresql/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -459,7 +459,7 @@ def list_backups( api_path = '/postgresql/{databaseId}/backups' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if queries is not None: @@ -504,7 +504,7 @@ def create_backup( api_path = '/postgresql/{databaseId}/backups' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if type is not None: @@ -550,7 +550,7 @@ def list_backup_policies( api_path = '/postgresql/{databaseId}/backups/policies' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if queries is not None: @@ -610,7 +610,7 @@ def create_backup_policy( api_path = '/postgresql/{databaseId}/backups/policies' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if policy_id is None: raise AppwriteException('Missing required parameter: "policy_id"') @@ -670,9 +670,9 @@ def get_backup_policy( api_path = '/postgresql/{databaseId}/backups/policies/{policyId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if policy_id is None: + if policy_id is None or policy_id == '': raise AppwriteException('Missing required parameter: "policy_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{policyId}', str(self._normalize_value(policy_id))) @@ -728,9 +728,9 @@ def update_backup_policy( api_path = '/postgresql/{databaseId}/backups/policies/{policyId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if policy_id is None: + if policy_id is None or policy_id == '': raise AppwriteException('Missing required parameter: "policy_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{policyId}', str(self._normalize_value(policy_id))) @@ -783,9 +783,9 @@ def delete_backup_policy( api_path = '/postgresql/{databaseId}/backups/policies/{policyId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if policy_id is None: + if policy_id is None or policy_id == '': raise AppwriteException('Missing required parameter: "policy_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{policyId}', str(self._normalize_value(policy_id))) @@ -848,7 +848,7 @@ def update_backup_storage( api_path = '/postgresql/{databaseId}/backups/storage' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if provider is None: raise AppwriteException('Missing required parameter: "provider"') @@ -910,9 +910,9 @@ def get_backup( api_path = '/postgresql/{databaseId}/backups/{backupId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if backup_id is None: + if backup_id is None or backup_id == '': raise AppwriteException('Missing required parameter: "backup_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{backupId}', str(self._normalize_value(backup_id))) @@ -956,9 +956,9 @@ def delete_backup( api_path = '/postgresql/{databaseId}/backups/{backupId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if backup_id is None: + if backup_id is None or backup_id == '': raise AppwriteException('Missing required parameter: "backup_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{backupId}', str(self._normalize_value(backup_id))) @@ -1000,7 +1000,7 @@ def list_branches( api_path = '/postgresql/{databaseId}/branches' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1046,7 +1046,7 @@ def create_branch( api_path = '/postgresql/{databaseId}/branches' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if branch_id is not None: @@ -1094,9 +1094,9 @@ def delete_branch( api_path = '/postgresql/{databaseId}/branches/{branchId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if branch_id is None: + if branch_id is None or branch_id == '': raise AppwriteException('Missing required parameter: "branch_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{branchId}', str(self._normalize_value(branch_id))) @@ -1138,7 +1138,7 @@ def update_credentials( api_path = '/postgresql/{databaseId}/credentials' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1163,7 +1163,7 @@ def create_execution( timeout_seconds: Optional[float] = None, ) -> DedicatedDatabaseExecution: """ - Execute SQL through the console-facing Cloud endpoint. Cloud proxies through the edge platform to the per-database SQL API sidecar. Application traffic should bypass cloud entirely and POST directly to the per-database hostname: `https://db-{project}-{db}.{region}.appwrite.center/v1/sql/executions` with an `X-Appwrite-Key` header — that path scales to the whole DB fleet without a per-query cloud round-trip. The statement type must be on the database's configured allow-list. Use bound parameters for any user-supplied values — the API does not interpolate raw strings. + Execute SQL through the console-facing Cloud endpoint. Cloud proxies through the edge platform to the per-database SQL API sidecar. Application traffic should bypass cloud entirely and POST directly to the per-database hostname: `https://db-{project}-{db}.{region}.appwrite.center/v1/sql/executions` with an `X-Appwrite-Key` header — that path scales to the whole DB fleet without a per-query cloud round-trip. The statement type must be on the database's configured allow-list. Use bound parameters for any user-supplied values — the API does not interpolate raw strings. Long-running statements (for example CREATE INDEX) can outlive the HTTP request: if the request ends before a result is returned, check the database before retrying, and prefer a direct connection for work that may take minutes. Parameters ---------- @@ -1174,7 +1174,7 @@ def create_execution( bindings : Optional[Dict[str, Any]] Optional bound parameters. Pass either a positional list or a name => value map matching the placeholder style used in the SQL. timeout_seconds : Optional[float] - Per-call execution timeout override. Must be less than or equal to the database's configured sqlApiTimeoutSeconds. + Per-call execution timeout override. Must be less than or equal to the database's configured sqlApiTimeoutSeconds. Statements that may exceed this — or the HTTP request timeout in front of Cloud — should use a direct connection instead. Returns ------- DedicatedDatabaseExecution @@ -1188,7 +1188,7 @@ def create_execution( api_path = '/postgresql/{databaseId}/executions' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if sql is None: raise AppwriteException('Missing required parameter: "sql"') @@ -1236,7 +1236,7 @@ def list_extensions( api_path = '/postgresql/{databaseId}/extensions' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1279,7 +1279,7 @@ def create_extension( api_path = '/postgresql/{databaseId}/extensions' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -1326,9 +1326,9 @@ def delete_extension( api_path = '/postgresql/{databaseId}/extensions/{extensionName}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if extension_name is None: + if extension_name is None or extension_name == '': raise AppwriteException('Missing required parameter: "extension_name"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{extensionName}', str(self._normalize_value(extension_name))) @@ -1373,7 +1373,7 @@ def create_failover( api_path = '/postgresql/{databaseId}/failovers' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if target_replica_id is not None: @@ -1422,7 +1422,7 @@ def update_maintenance( api_path = '/postgresql/{databaseId}/maintenance' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if day is None: raise AppwriteException('Missing required parameter: "day"') @@ -1475,7 +1475,7 @@ def create_migration( api_path = '/postgresql/{databaseId}/migrations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if target_type is None: raise AppwriteException('Missing required parameter: "target_type"') @@ -1530,7 +1530,7 @@ def list_operations( api_path = '/postgresql/{databaseId}/operations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if status is not None: @@ -1576,7 +1576,7 @@ def get_pitr( api_path = '/postgresql/{databaseId}/pitr' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1616,7 +1616,7 @@ def get_pooler( api_path = '/postgresql/{databaseId}/pooler' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1658,7 +1658,7 @@ def update_pooler( default_pool_size : Optional[float] Default pool size per user. read_write_splitting : Optional[bool] - Route SELECTs to HA replicas, writes and locked reads to the primary. Defaults to true when HA is enabled. + Route SELECTs to HA replicas, writes and locked reads to the primary. Off by default, and only takes effect while HA is enabled. Replication is asynchronous, so a read issued immediately after a write may not observe it. pooler_cpu_request : Optional[str] Pooler sidecar CPU request override (Kubernetes quantity, e.g. "250m" or "1"). Leave null for the proportional default (5% of DB CPU, floor 100m). pooler_cpu_limit : Optional[str] @@ -1680,7 +1680,7 @@ def update_pooler( api_path = '/postgresql/{databaseId}/pooler' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if mode is not None: @@ -1737,7 +1737,7 @@ def get_replicas( api_path = '/postgresql/{databaseId}/replicas' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1789,7 +1789,7 @@ def list_restorations( api_path = '/postgresql/{databaseId}/restorations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if status is not None: @@ -1820,10 +1820,15 @@ def create_restoration( backup_id: Optional[str] = None, target_database_id: Optional[str] = None, target_time: Optional[str] = None, + restore_mode: Optional[str] = None, + target_name: Optional[str] = None, + auto_promote: Optional[bool] = None, ) -> DedicatedDatabaseRestoration: """ Restore a database from a backup or to a specific point in time (PITR). For backup restoration, provide a backupId. For PITR, provide a targetTime as an ISO 8601 datetime. PITR requires the database to have PITR enabled and is only available for enterprise databases. + By default the backup is replayed over the database it was taken from. Pass `restoreMode` as `clone` to recover it onto a second workload beside this database instead: this database keeps serving its own data while the clone is filled, and the switch happens as soon as the clone is ready, on the endpoint and credentials it already had. Pass `autoPromote` as false to hold the clone until you promote it yourself. Pass `restoreMode` as `copy` to recover onto a separate database with its own endpoint, either one you name with `targetDatabaseId` or one provisioned as a copy of this database's engine, version, specification and replicas. Neither mode is available for a point-in-time recovery or an incremental backup. + Parameters ---------- database_id : str @@ -1833,9 +1838,15 @@ def create_restoration( backup_id : Optional[str] Backup ID to restore from (required for backup type). target_database_id : Optional[str] - Existing database ID to restore into. The target must be distinct, ready, and use the same engine and version. + Existing database ID to restore into. The target must be distinct, ready, and use the same engine and version. Omit it on a copy restoration to have one provisioned. Not accepted for a clone, which is recovered inside this database. target_time : Optional[str] Target time for PITR (required for pitr type) as an [ISO 8601](https://www.iso.org/iso-8601-date-and-time-format.html) datetime. + restore_mode : Optional[str] + Where the backup is restored. Allowed values: in_place, clone, copy. Use "clone" to recover onto a second workload beside this database and leave it serving until you promote — the endpoint and credentials do not change. Use "copy" to recover onto a separate database with its own endpoint, either one you name with targetDatabaseId or one Cloud provisions. Use "in_place" to replay the backup over this database. Defaults to "copy" when a targetDatabaseId is given, "in_place" otherwise. + target_name : Optional[str] + Display name for the database a copy restoration provisions. Defaults to this database's name followed by "(restored)". Max length: 128 chars. + auto_promote : Optional[bool] + Whether a clone restoration switches the database over as soon as the recovery is ready. Default true: the restore finishes with the database serving the recovery point on the endpoint it already had, and the side it replaced kept briefly so the switch can be reversed. Pass false to hold the recovery until you call the promotion endpoint yourself. Returns ------- DedicatedDatabaseRestoration @@ -1849,7 +1860,7 @@ def create_restoration( api_path = '/postgresql/{databaseId}/restorations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if type is not None: @@ -1860,6 +1871,12 @@ def create_restoration( api_params['targetDatabaseId'] = self._normalize_value(target_database_id) if target_time is not None: api_params['targetTime'] = self._normalize_value(target_time) + if restore_mode is not None: + api_params['restoreMode'] = self._normalize_value(restore_mode) + if target_name is not None: + api_params['targetName'] = self._normalize_value(target_name) + if auto_promote is not None: + api_params['autoPromote'] = self._normalize_value(auto_promote) response = self.client.call( 'post', @@ -1901,9 +1918,9 @@ def get_restoration( api_path = '/postgresql/{databaseId}/restorations/{restorationId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if restoration_id is None: + if restoration_id is None or restoration_id == '': raise AppwriteException('Missing required parameter: "restoration_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{restorationId}', str(self._normalize_value(restoration_id))) @@ -1920,6 +1937,56 @@ def get_restoration( return self._parse_response(response, model=DedicatedDatabaseRestoration) + def promote_restoration( + self, + database_id: str, + restoration_id: str, + ) -> DedicatedDatabaseRestoration: + """ + Switch the database over to the clone a restoration recovered. The database keeps + its endpoint and credentials; clients reconnect once. Writes made after the + recovery point are discarded, and the side being replaced is retained briefly so + the switch can be reversed. + + Parameters + ---------- + database_id : str + Database ID. + restoration_id : str + Restoration ID. + Returns + ------- + DedicatedDatabaseRestoration + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/postgresql/{databaseId}/restorations/{restorationId}/promotions' + api_params = {} + if database_id is None or database_id == '': + raise AppwriteException('Missing required parameter: "database_id"') + if restoration_id is None or restoration_id == '': + raise AppwriteException('Missing required parameter: "restoration_id"') + api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) + api_path = api_path.replace('{restorationId}', str(self._normalize_value(restoration_id))) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=DedicatedDatabaseRestoration) + def get_status( self, database_id: str, @@ -1944,7 +2011,7 @@ def get_status( api_path = '/postgresql/{databaseId}/status' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1987,7 +2054,7 @@ def create_upgrade( api_path = '/postgresql/{databaseId}/upgrades' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if target_version is None: raise AppwriteException('Missing required parameter: "target_version"') diff --git a/appwrite/services/presences.py b/appwrite/services/presences.py index d4caaa86..7066914a 100644 --- a/appwrite/services/presences.py +++ b/appwrite/services/presences.py @@ -85,7 +85,7 @@ def get( api_path = '/presences/{presenceId}' api_params = {} - if presence_id is None: + if presence_id is None or presence_id == '': raise AppwriteException('Missing required parameter: "presence_id"') api_path = api_path.replace('{presenceId}', str(self._normalize_value(presence_id))) @@ -140,7 +140,7 @@ def upsert( api_path = '/presences/{presenceId}' api_params = {} - if presence_id is None: + if presence_id is None or presence_id == '': raise AppwriteException('Missing required parameter: "presence_id"') if user_id is None: raise AppwriteException('Missing required parameter: "user_id"') @@ -211,7 +211,7 @@ def update( api_path = '/presences/{presenceId}' api_params = {} - if presence_id is None: + if presence_id is None or presence_id == '': raise AppwriteException('Missing required parameter: "presence_id"') if user_id is None: raise AppwriteException('Missing required parameter: "user_id"') @@ -265,7 +265,7 @@ def delete( api_path = '/presences/{presenceId}' api_params = {} - if presence_id is None: + if presence_id is None or presence_id == '': raise AppwriteException('Missing required parameter: "presence_id"') api_path = api_path.replace('{presenceId}', str(self._normalize_value(presence_id))) @@ -275,6 +275,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) diff --git a/appwrite/services/project.py b/appwrite/services/project.py index d049fcbd..3de8bfc2 100644 --- a/appwrite/services/project.py +++ b/appwrite/services/project.py @@ -137,6 +137,7 @@ def get( api_path, { 'X-Appwrite-Project': self.client.get_config('project'), + 'accept': 'application/json', }, api_params, ) @@ -168,6 +169,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -185,7 +187,7 @@ def update_auth_method( Parameters ---------- method_id : ProjectAuthMethodId - Auth Method ID. Possible values: email-password,magic-url,email-otp,anonymous,invites,jwt,phone + Auth Method ID. Possible values: email-password,magic-url,email-otp,anonymous,invites,jwt,phone,passkey enabled : bool Auth method status. Returns @@ -557,7 +559,7 @@ def get_key( api_path = '/project/keys/{keyId}' api_params = {} - if key_id is None: + if key_id is None or key_id == '': raise AppwriteException('Missing required parameter: "key_id"') api_path = api_path.replace('{keyId}', str(self._normalize_value(key_id))) @@ -606,7 +608,7 @@ def update_key( api_path = '/project/keys/{keyId}' api_params = {} - if key_id is None: + if key_id is None or key_id == '': raise AppwriteException('Missing required parameter: "key_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -655,7 +657,7 @@ def delete_key( api_path = '/project/keys/{keyId}' api_params = {} - if key_id is None: + if key_id is None or key_id == '': raise AppwriteException('Missing required parameter: "key_id"') api_path = api_path.replace('{keyId}', str(self._normalize_value(key_id))) @@ -665,6 +667,7 @@ def delete_key( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -827,7 +830,7 @@ def get_mock_phone( api_path = '/project/mock-phones/{number}' api_params = {} - if number is None: + if number is None or number == '': raise AppwriteException('Missing required parameter: "number"') api_path = api_path.replace('{number}', str(self._normalize_value(number))) @@ -870,7 +873,7 @@ def update_mock_phone( api_path = '/project/mock-phones/{number}' api_params = {} - if number is None: + if number is None or number == '': raise AppwriteException('Missing required parameter: "number"') if otp is None: raise AppwriteException('Missing required parameter: "otp"') @@ -914,7 +917,7 @@ def delete_mock_phone( api_path = '/project/mock-phones/{number}' api_params = {} - if number is None: + if number is None or number == '': raise AppwriteException('Missing required parameter: "number"') api_path = api_path.replace('{number}', str(self._normalize_value(number))) @@ -924,6 +927,7 @@ def delete_mock_phone( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -2265,8 +2269,8 @@ def update_o_auth2_kakao( self, client_id: Optional[str] = None, client_secret: Optional[str] = None, - prompt: Optional[List[ProjectOAuth2KakaoPrompt]] = None, enabled: Optional[bool] = None, + prompt: Optional[List[ProjectOAuth2KakaoPrompt]] = None, ) -> OAuth2Kakao: """ Update the project OAuth2 Kakao configuration. @@ -2277,10 +2281,10 @@ def update_o_auth2_kakao( 'REST API key' of Kakao OAuth2 app. For example: 839ff5000000000000000000013206de client_secret : Optional[str] 'Client Secret' of Kakao OAuth2 app. For example: jLNVOK00000000000000000000yJebea. Generate it under Kakao Login > Security and set its status to enabled - prompt : Optional[List[ProjectOAuth2KakaoPrompt]] - Array of Kakao OAuth2 prompt values. If "none" is included, it must be the only element. "none" means: don't display any authentication or consent screens. "login" means: prompt the user to re-authenticate. "create" means: prompt the user to sign up. "select_account" means: prompt the user to select an account. Pass an empty array to use the Kakao default. enabled : Optional[bool] OAuth2 sign-in method status. Set to true to enable new session creation. Setting to true will trigger end-to-end credentials validation, and will throw if the credentials are invalid. + prompt : Optional[List[ProjectOAuth2KakaoPrompt]] + Array of Kakao OAuth2 prompt values. If "none" is included, it must be the only element. "none" means: don't display any authentication or consent screens. "login" means: prompt the user to re-authenticate. "create" means: prompt the user to sign up. "select_account" means: prompt the user to select an account. Pass an empty array to use the Kakao default. Returns ------- OAuth2Kakao @@ -2298,10 +2302,10 @@ def update_o_auth2_kakao( api_params['clientId'] = self._normalize_value(client_id) if client_secret is not None: api_params['clientSecret'] = self._normalize_value(client_secret) - if prompt is not None: - api_params['prompt'] = self._normalize_value(prompt) if enabled is not None: api_params['enabled'] = self._normalize_value(enabled) + if prompt is not None: + api_params['prompt'] = self._normalize_value(prompt) response = self.client.call( 'patch', @@ -4028,7 +4032,7 @@ def update_android_platform( fingerprints: Optional[List[str]] = None, ) -> PlatformAndroid: """ - Update an Android platform by its unique ID. Use this endpoint to update the platform's name or application ID. + Update an Android platform by its unique ID. Use this endpoint to update the platform's name, application ID or signing certificate fingerprints. Parameters ---------- @@ -4053,7 +4057,7 @@ def update_android_platform( api_path = '/project/platforms/android/{platformId}' api_params = {} - if platform_id is None: + if platform_id is None or platform_id == '': raise AppwriteException('Missing required parameter: "platform_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -4161,7 +4165,7 @@ def update_apple_platform( api_path = '/project/platforms/apple/{platformId}' api_params = {} - if platform_id is None: + if platform_id is None or platform_id == '': raise AppwriteException('Missing required parameter: "platform_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -4267,7 +4271,7 @@ def update_linux_platform( api_path = '/project/platforms/linux/{platformId}' api_params = {} - if platform_id is None: + if platform_id is None or platform_id == '': raise AppwriteException('Missing required parameter: "platform_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -4373,7 +4377,7 @@ def update_web_platform( api_path = '/project/platforms/web/{platformId}' api_params = {} - if platform_id is None: + if platform_id is None or platform_id == '': raise AppwriteException('Missing required parameter: "platform_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -4479,7 +4483,7 @@ def update_windows_platform( api_path = '/project/platforms/windows/{platformId}' api_params = {} - if platform_id is None: + if platform_id is None or platform_id == '': raise AppwriteException('Missing required parameter: "platform_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -4532,7 +4536,7 @@ def get_platform( api_path = '/project/platforms/{platformId}' api_params = {} - if platform_id is None: + if platform_id is None or platform_id == '': raise AppwriteException('Missing required parameter: "platform_id"') api_path = api_path.replace('{platformId}', str(self._normalize_value(platform_id))) @@ -4589,7 +4593,7 @@ def delete_platform( api_path = '/project/platforms/{platformId}' api_params = {} - if platform_id is None: + if platform_id is None or platform_id == '': raise AppwriteException('Missing required parameter: "platform_id"') api_path = api_path.replace('{platformId}', str(self._normalize_value(platform_id))) @@ -4599,6 +4603,7 @@ def delete_platform( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -5484,7 +5489,7 @@ def get_policy( Parameters ---------- policy_id : ProjectPolicyId - Policy ID. Can be one of: password-dictionary, password-history, password-strength, password-personal-data, session-alert, session-duration, session-invalidation, session-limit, user-limit, membership-privacy, mfa-factors, deny-aliased-email, deny-disposable-email, deny-free-email, deny-corporate-email. + Policy ID. Can be one of: password-dictionary, password-history, password-strength, password-personal-data, password-pwned, password-rotation, session-alert, session-duration, session-invalidation, session-limit, user-limit, membership-privacy, mfa-factors, deny-aliased-email, deny-disposable-email, deny-free-email, deny-corporate-email, passkey. Returns ------- Union[PolicyPasswordDictionary, PolicyPasswordHistory, PolicyPasswordStrength, PolicyPasswordPersonalData, PolicyPasswordPwned, PolicyPasswordRotation, PolicySessionAlert, PolicySessionDuration, PolicySessionInvalidation, PolicySessionLimit, PolicyUserLimit, PolicyMembershipPrivacy, PolicyMfaFactors, PolicyDenyAliasedEmail, PolicyDenyDisposableEmail, PolicyDenyFreeEmail, PolicyDenyCorporateEmail, PolicyPasskey] @@ -5783,6 +5788,7 @@ def create_smtp_test( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -5850,7 +5856,7 @@ def update_email_template( Parameters ---------- template_id : ProjectEmailTemplateId - Custom email template type. Can be one of: verification, magicSession, recovery, invitation, mfaChallenge, sessionAlert, otpSession + Custom email template type. Can be one of: verification, magicSession, recovery, invitation, mfaChallenge, sessionAlert, otpSession, otpVerification, otpRecovery locale : Optional[ProjectEmailTemplateLocale] Custom email template locale. If left empty, the fallback locale (en) will be used. subject : Optional[str] @@ -5920,7 +5926,7 @@ def get_email_template( Parameters ---------- template_id : ProjectEmailTemplateId - Custom email template type. Can be one of: verification, magicSession, recovery, invitation, mfaChallenge, sessionAlert, otpSession + Custom email template type. Can be one of: verification, magicSession, recovery, invitation, mfaChallenge, sessionAlert, otpSession, otpVerification, otpRecovery locale : Optional[ProjectEmailTemplateLocale] Custom email template locale. If left empty, the fallback locale (en) will be used. Returns @@ -6080,7 +6086,7 @@ def get_variable( api_path = '/project/variables/{variableId}' api_params = {} - if variable_id is None: + if variable_id is None or variable_id == '': raise AppwriteException('Missing required parameter: "variable_id"') api_path = api_path.replace('{variableId}', str(self._normalize_value(variable_id))) @@ -6129,7 +6135,7 @@ def update_variable( api_path = '/project/variables/{variableId}' api_params = {} - if variable_id is None: + if variable_id is None or variable_id == '': raise AppwriteException('Missing required parameter: "variable_id"') api_path = api_path.replace('{variableId}', str(self._normalize_value(variable_id))) if key is not None: @@ -6176,7 +6182,7 @@ def delete_variable( api_path = '/project/variables/{variableId}' api_params = {} - if variable_id is None: + if variable_id is None or variable_id == '': raise AppwriteException('Missing required parameter: "variable_id"') api_path = api_path.replace('{variableId}', str(self._normalize_value(variable_id))) @@ -6186,6 +6192,7 @@ def delete_variable( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) diff --git a/appwrite/services/proxy.py b/appwrite/services/proxy.py index 0429a4e9..5f4e5c68 100644 --- a/appwrite/services/proxy.py +++ b/appwrite/services/proxy.py @@ -27,6 +27,8 @@ def create_invalidation( Depending on type, the invalidation purges a single cache tag, a single URL path, or all cached content for the domain. + Domains that route to a function do not support cache invalidation. + Parameters ---------- domain : str @@ -81,7 +83,7 @@ def list_rules( Parameters ---------- queries : Optional[List[str]] - Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: domain, type, trigger, deploymentResourceType, deploymentResourceId, deploymentId, deploymentVcsProviderBranch + Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/databases#querying-documents). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: domain, type, trigger, deploymentResourceType, deploymentResourceId, deploymentId, deploymentVcsProviderBranch, protocol total : Optional[bool] When set to false, the total count returned will be 0 and will not be calculated. Returns @@ -332,6 +334,58 @@ def create_site_rule( return self._parse_response(response, model=ProxyRule) + def create_smtp_rule( + self, + domain: str, + function_id: str, + branch: Optional[str] = None, + ) -> ProxyRule: + """ + Create an SMTP ingress rule that asynchronously executes an Appwrite Function for incoming email. + + Parameters + ---------- + domain : str + Domain that receives email. + function_id : str + ID of function to execute. + branch : Optional[str] + Name of VCS branch to deploy changes automatically. + Returns + ------- + ProxyRule + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/proxy/rules/smtp' + api_params = {} + if domain is None: + raise AppwriteException('Missing required parameter: "domain"') + if function_id is None: + raise AppwriteException('Missing required parameter: "function_id"') + api_params['domain'] = self._normalize_value(domain) + api_params['functionId'] = self._normalize_value(function_id) + if branch is not None: + api_params['branch'] = self._normalize_value(branch) + + response = self.client.call( + 'post', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=ProxyRule) + def get_rule( self, rule_id: str, @@ -356,7 +410,7 @@ def get_rule( api_path = '/proxy/rules/{ruleId}' api_params = {} - if rule_id is None: + if rule_id is None or rule_id == '': raise AppwriteException('Missing required parameter: "rule_id"') api_path = api_path.replace('{ruleId}', str(self._normalize_value(rule_id))) @@ -396,7 +450,7 @@ def delete_rule( api_path = '/proxy/rules/{ruleId}' api_params = {} - if rule_id is None: + if rule_id is None or rule_id == '': raise AppwriteException('Missing required parameter: "rule_id"') api_path = api_path.replace('{ruleId}', str(self._normalize_value(rule_id))) @@ -406,6 +460,7 @@ def delete_rule( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -436,7 +491,7 @@ def update_rule_status( api_path = '/proxy/rules/{ruleId}/status' api_params = {} - if rule_id is None: + if rule_id is None or rule_id == '': raise AppwriteException('Missing required parameter: "rule_id"') api_path = api_path.replace('{ruleId}', str(self._normalize_value(rule_id))) diff --git a/appwrite/services/sites.py b/appwrite/services/sites.py index 3766cce7..952e4b27 100644 --- a/appwrite/services/sites.py +++ b/appwrite/services/sites.py @@ -343,7 +343,7 @@ def get( api_path = '/sites/{siteId}' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) @@ -452,7 +452,7 @@ def update( api_path = '/sites/{siteId}' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -541,7 +541,7 @@ def delete( api_path = '/sites/{siteId}' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) @@ -551,6 +551,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -584,7 +585,7 @@ def update_site_deployment( api_path = '/sites/{siteId}/deployment' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') if deployment_id is None: raise AppwriteException('Missing required parameter: "deployment_id"') @@ -637,7 +638,7 @@ def list_deployments( api_path = '/sites/{siteId}/deployments' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) if queries is not None: @@ -702,7 +703,7 @@ def create_deployment( api_path = '/sites/{siteId}/deployments' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') if code is None: raise AppwriteException('Missing required parameter: "code"') @@ -734,6 +735,7 @@ def create_deployment( param_name, on_progress, upload_id, + method='post', ) return self._parse_response(response, model=Deployment) @@ -765,7 +767,7 @@ def create_duplicate_deployment( api_path = '/sites/{siteId}/deployments/duplicate' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') if deployment_id is None: raise AppwriteException('Missing required parameter: "deployment_id"') @@ -829,7 +831,7 @@ def create_template_deployment( api_path = '/sites/{siteId}/deployments/template' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') if repository is None: raise AppwriteException('Missing required parameter: "repository"') @@ -898,7 +900,7 @@ def create_vcs_deployment( api_path = '/sites/{siteId}/deployments/vcs' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') if type is None: raise AppwriteException('Missing required parameter: "type"') @@ -950,9 +952,9 @@ def get_deployment( api_path = '/sites/{siteId}/deployments/{deploymentId}' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') - if deployment_id is None: + if deployment_id is None or deployment_id == '': raise AppwriteException('Missing required parameter: "deployment_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) api_path = api_path.replace('{deploymentId}', str(self._normalize_value(deployment_id))) @@ -996,9 +998,9 @@ def delete_deployment( api_path = '/sites/{siteId}/deployments/{deploymentId}' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') - if deployment_id is None: + if deployment_id is None or deployment_id == '': raise AppwriteException('Missing required parameter: "deployment_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) api_path = api_path.replace('{deploymentId}', str(self._normalize_value(deployment_id))) @@ -1009,6 +1011,7 @@ def delete_deployment( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -1048,9 +1051,9 @@ def get_deployment_download( api_path = '/sites/{siteId}/deployments/{deploymentId}/download' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') - if deployment_id is None: + if deployment_id is None or deployment_id == '': raise AppwriteException('Missing required parameter: "deployment_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) api_path = api_path.replace('{deploymentId}', str(self._normalize_value(deployment_id))) @@ -1098,9 +1101,9 @@ def update_deployment_status( api_path = '/sites/{siteId}/deployments/{deploymentId}/status' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') - if deployment_id is None: + if deployment_id is None or deployment_id == '': raise AppwriteException('Missing required parameter: "deployment_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) api_path = api_path.replace('{deploymentId}', str(self._normalize_value(deployment_id))) @@ -1148,7 +1151,7 @@ def list_logs( api_path = '/sites/{siteId}/logs' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) if queries is not None: @@ -1195,9 +1198,9 @@ def get_log( api_path = '/sites/{siteId}/logs/{logId}' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') - if log_id is None: + if log_id is None or log_id == '': raise AppwriteException('Missing required parameter: "log_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) api_path = api_path.replace('{logId}', str(self._normalize_value(log_id))) @@ -1241,9 +1244,9 @@ def delete_log( api_path = '/sites/{siteId}/logs/{logId}' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') - if log_id is None: + if log_id is None or log_id == '': raise AppwriteException('Missing required parameter: "log_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) api_path = api_path.replace('{logId}', str(self._normalize_value(log_id))) @@ -1291,7 +1294,7 @@ def list_variables( api_path = '/sites/{siteId}/variables' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) if queries is not None: @@ -1347,7 +1350,7 @@ def create_variable( api_path = '/sites/{siteId}/variables' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') if variable_id is None: raise AppwriteException('Missing required parameter: "variable_id"') @@ -1402,9 +1405,9 @@ def get_variable( api_path = '/sites/{siteId}/variables/{variableId}' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') - if variable_id is None: + if variable_id is None or variable_id == '': raise AppwriteException('Missing required parameter: "variable_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) api_path = api_path.replace('{variableId}', str(self._normalize_value(variable_id))) @@ -1457,9 +1460,9 @@ def update_variable( api_path = '/sites/{siteId}/variables/{variableId}' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') - if variable_id is None: + if variable_id is None or variable_id == '': raise AppwriteException('Missing required parameter: "variable_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) api_path = api_path.replace('{variableId}', str(self._normalize_value(variable_id))) @@ -1510,9 +1513,9 @@ def delete_variable( api_path = '/sites/{siteId}/variables/{variableId}' api_params = {} - if site_id is None: + if site_id is None or site_id == '': raise AppwriteException('Missing required parameter: "site_id"') - if variable_id is None: + if variable_id is None or variable_id == '': raise AppwriteException('Missing required parameter: "variable_id"') api_path = api_path.replace('{siteId}', str(self._normalize_value(site_id))) api_path = api_path.replace('{variableId}', str(self._normalize_value(variable_id))) @@ -1523,6 +1526,7 @@ def delete_variable( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) diff --git a/appwrite/services/storage.py b/appwrite/services/storage.py index 7e4f647d..a095f6d2 100644 --- a/appwrite/services/storage.py +++ b/appwrite/services/storage.py @@ -183,7 +183,7 @@ def get_bucket( api_path = '/storage/buckets/{bucketId}' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') api_path = api_path.replace('{bucketId}', str(self._normalize_value(bucket_id))) @@ -253,7 +253,7 @@ def update_bucket( api_path = '/storage/buckets/{bucketId}' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -315,7 +315,7 @@ def delete_bucket( api_path = '/storage/buckets/{bucketId}' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') api_path = api_path.replace('{bucketId}', str(self._normalize_value(bucket_id))) @@ -325,6 +325,7 @@ def delete_bucket( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -364,7 +365,7 @@ def list_files( api_path = '/storage/buckets/{bucketId}/files' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') api_path = api_path.replace('{bucketId}', str(self._normalize_value(bucket_id))) if queries is not None: @@ -432,7 +433,7 @@ def create_file( api_path = '/storage/buckets/{bucketId}/files' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') if file_id is None: raise AppwriteException('Missing required parameter: "file_id"') @@ -462,6 +463,7 @@ def create_file( param_name, on_progress, upload_id, + method='post', ) return self._parse_response(response, model=File) @@ -493,9 +495,9 @@ def get_file( api_path = '/storage/buckets/{bucketId}/files/{fileId}' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') - if file_id is None: + if file_id is None or file_id == '': raise AppwriteException('Missing required parameter: "file_id"') api_path = api_path.replace('{bucketId}', str(self._normalize_value(bucket_id))) api_path = api_path.replace('{fileId}', str(self._normalize_value(file_id))) @@ -545,9 +547,9 @@ def update_file( api_path = '/storage/buckets/{bucketId}/files/{fileId}' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') - if file_id is None: + if file_id is None or file_id == '': raise AppwriteException('Missing required parameter: "file_id"') api_path = api_path.replace('{bucketId}', str(self._normalize_value(bucket_id))) api_path = api_path.replace('{fileId}', str(self._normalize_value(file_id))) @@ -596,9 +598,9 @@ def delete_file( api_path = '/storage/buckets/{bucketId}/files/{fileId}' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') - if file_id is None: + if file_id is None or file_id == '': raise AppwriteException('Missing required parameter: "file_id"') api_path = api_path.replace('{bucketId}', str(self._normalize_value(bucket_id))) api_path = api_path.replace('{fileId}', str(self._normalize_value(file_id))) @@ -609,6 +611,7 @@ def delete_file( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -645,9 +648,9 @@ def get_file_download( api_path = '/storage/buckets/{bucketId}/files/{fileId}/download' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') - if file_id is None: + if file_id is None or file_id == '': raise AppwriteException('Missing required parameter: "file_id"') api_path = api_path.replace('{bucketId}', str(self._normalize_value(bucket_id))) api_path = api_path.replace('{fileId}', str(self._normalize_value(file_id))) @@ -697,7 +700,7 @@ def get_file_preview( height : Optional[float] Resize preview image height, Pass an integer between 0 to 4000. gravity : Optional[ImageGravity] - Image crop gravity. Can be one of center,top-left,top,top-right,left,right,bottom-left,bottom,bottom-right + Image crop gravity. Can be one of auto,center,top-left,top,top-right,left,right,bottom-left,bottom,bottom-right quality : Optional[float] Preview image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality. border_width : Optional[float] @@ -729,9 +732,9 @@ def get_file_preview( api_path = '/storage/buckets/{bucketId}/files/{fileId}/preview' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') - if file_id is None: + if file_id is None or file_id == '': raise AppwriteException('Missing required parameter: "file_id"') api_path = api_path.replace('{bucketId}', str(self._normalize_value(bucket_id))) api_path = api_path.replace('{fileId}', str(self._normalize_value(file_id))) @@ -802,9 +805,9 @@ def get_file_view( api_path = '/storage/buckets/{bucketId}/files/{fileId}/view' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') - if file_id is None: + if file_id is None or file_id == '': raise AppwriteException('Missing required parameter: "file_id"') api_path = api_path.replace('{bucketId}', str(self._normalize_value(bucket_id))) api_path = api_path.replace('{fileId}', str(self._normalize_value(file_id))) diff --git a/appwrite/services/tables_db.py b/appwrite/services/tables_db.py index 17ed9f8d..6a90c3a8 100644 --- a/appwrite/services/tables_db.py +++ b/appwrite/services/tables_db.py @@ -172,7 +172,7 @@ def list_specifications( self, ) -> DedicatedDatabaseSpecificationList: """ - List the dedicated database specifications available on the current plan. Each specification reports its resource limits, pricing, and whether it is enabled for the organization. + List the dedicated database specifications available on the current plan. Each specification reports its resource limits, its own prices and overage rates, and whether it is enabled for the organization. Returns ------- DedicatedDatabaseSpecificationList @@ -307,7 +307,7 @@ def get_transaction( api_path = '/tablesdb/transactions/{transactionId}' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) @@ -353,7 +353,7 @@ def update_transaction( api_path = '/tablesdb/transactions/{transactionId}' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) if commit is not None: @@ -398,7 +398,7 @@ def delete_transaction( api_path = '/tablesdb/transactions/{transactionId}' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) @@ -408,6 +408,7 @@ def delete_transaction( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -441,7 +442,7 @@ def create_operations( api_path = '/tablesdb/transactions/{transactionId}/operations' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) if operations is not None: @@ -484,7 +485,7 @@ def get( api_path = '/tablesdb/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -539,7 +540,7 @@ def update( api_path = '/tablesdb/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if name is not None: @@ -590,7 +591,7 @@ def delete( api_path = '/tablesdb/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -600,6 +601,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -633,7 +635,7 @@ def create_failover( api_path = '/tablesdb/{databaseId}/failovers' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if target_replica_id is not None: @@ -676,7 +678,7 @@ def list_migrations( api_path = '/tablesdb/{databaseId}/migrations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -699,7 +701,7 @@ def create_migration( auto_cutover: Optional[bool] = None, ) -> DatabaseMigration: """ - Start migrating a serverless TablesDB database onto a dedicated MySQL compute. Data is copied to the target while the source stays live, with a brief read-only window during cutover. + Start migrating a serverless TablesDB database onto a dedicated MySQL compute. Data is copied to the target while the source stays live. Reads continue throughout. Row writes are held for up to a few seconds while routing switches to the dedicated compute; a write the switch has not absorbed within that hold is refused with `database_migration_cutover` and can be retried. Schema changes (tables, columns, indexes) are refused from creation until the cutover completes, and resume once the migration is `soaking`. Parameters ---------- @@ -722,7 +724,7 @@ def create_migration( api_path = '/tablesdb/{databaseId}/migrations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if specification is None: raise AppwriteException('Missing required parameter: "specification"') @@ -771,9 +773,9 @@ def get_migration( api_path = '/tablesdb/{databaseId}/migrations/{migrationId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if migration_id is None: + if migration_id is None or migration_id == '': raise AppwriteException('Missing required parameter: "migration_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{migrationId}', str(self._normalize_value(migration_id))) @@ -817,9 +819,9 @@ def delete_migration( api_path = '/tablesdb/{databaseId}/migrations/{migrationId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if migration_id is None: + if migration_id is None or migration_id == '': raise AppwriteException('Missing required parameter: "migration_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{migrationId}', str(self._normalize_value(migration_id))) @@ -843,7 +845,7 @@ def create_cutover( migration_id: str, ) -> DatabaseMigration: """ - Cut a verified TablesDB migration over to its dedicated compute. Only applies to a migration created with `autoCutover` disabled, which waits at `ready_to_cutover` until this is called. The routing flip happens shortly after this returns, with a brief read-only window. One call buys one attempt: a cutover that fails a check returns the migration to `verifying` and parks it again, so call this once more to retry. + Cut a verified TablesDB migration over to its dedicated compute. Only applies to a migration created with `autoCutover` disabled, which waits at `ready_to_cutover` until this is called. The routing flip happens shortly after this returns. Reads are unaffected; row writes are held for up to a few seconds while it lands, and a write the flip has not absorbed within that hold is refused with `database_migration_cutover` and can be retried. One call buys one attempt: a cutover that fails a check returns the migration to `verifying` and parks it again, so call this once more to retry. Parameters ---------- @@ -864,9 +866,9 @@ def create_cutover( api_path = '/tablesdb/{databaseId}/migrations/{migrationId}/cutovers' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if migration_id is None: + if migration_id is None or migration_id == '': raise AppwriteException('Missing required parameter: "migration_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{migrationId}', str(self._normalize_value(migration_id))) @@ -917,7 +919,7 @@ def list_operations( api_path = '/tablesdb/{databaseId}/operations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if status is not None: @@ -963,7 +965,7 @@ def get_replicas( api_path = '/tablesdb/{databaseId}/replicas' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1003,7 +1005,7 @@ def get_status( api_path = '/tablesdb/{databaseId}/status' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -1052,7 +1054,7 @@ def list_tables( api_path = '/tablesdb/{databaseId}/tables' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if queries is not None: @@ -1105,7 +1107,7 @@ def create_table( columns : Optional[List[Dict[str, Any]]] Array of column definitions to create. Each column should contain: key (string), type (string: string, varchar, text, mediumtext, longtext, integer, bigint, double, boolean, datetime, point, linestring, polygon, email, url, ip, enum), size (integer, required for string and varchar types), required (boolean, optional), default (mixed, optional), array (boolean, optional), and type-specific options. indexes : Optional[List[Dict[str, Any]]] - Array of index definitions to create. Each index should contain: key (string), type (string: key, fulltext, unique, spatial), attributes (array of column keys), orders (array of ASC/DESC, optional), and lengths (array of integers, optional). + Array of index definitions to create. Each index should contain: key (string), type (string: key, fulltext, unique, spatial, trigram), attributes (array of column keys), orders (array of ASC/DESC, optional), and lengths (array of integers, optional). Returns ------- Table @@ -1119,7 +1121,7 @@ def create_table( api_path = '/tablesdb/{databaseId}/tables' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if table_id is None: raise AppwriteException('Missing required parameter: "table_id"') @@ -1179,9 +1181,9 @@ def get_table( api_path = '/tablesdb/{databaseId}/tables/{tableId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -1240,9 +1242,9 @@ def update_table( api_path = '/tablesdb/{databaseId}/tables/{tableId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -1297,9 +1299,9 @@ def delete_table( api_path = '/tablesdb/{databaseId}/tables/{tableId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -1310,6 +1312,7 @@ def delete_table( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -1349,9 +1352,9 @@ def list_columns( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -1417,9 +1420,9 @@ def create_big_int_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/bigint' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1496,11 +1499,11 @@ def update_big_int_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/bigint/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -1568,9 +1571,9 @@ def create_boolean_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/boolean' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1637,11 +1640,11 @@ def update_boolean_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/boolean/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -1705,9 +1708,9 @@ def create_datetime_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/datetime' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1774,11 +1777,11 @@ def update_datetime_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/datetime/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -1842,9 +1845,9 @@ def create_email_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/email' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1911,11 +1914,11 @@ def update_email_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/email/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -1982,9 +1985,9 @@ def create_enum_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/enum' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2057,11 +2060,11 @@ def update_enum_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/enum/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if elements is None: raise AppwriteException('Missing required parameter: "elements"') @@ -2134,9 +2137,9 @@ def create_float_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/float' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2213,11 +2216,11 @@ def update_float_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/float/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2291,9 +2294,9 @@ def create_integer_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/integer' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2370,11 +2373,11 @@ def update_integer_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/integer/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2442,9 +2445,9 @@ def create_ip_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/ip' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2511,11 +2514,11 @@ def update_ip_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/ip/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2576,9 +2579,9 @@ def create_line_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/line' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2643,11 +2646,11 @@ def update_line_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/line/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2715,9 +2718,9 @@ def create_longtext_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/longtext' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2786,11 +2789,11 @@ def update_longtext_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/longtext/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2857,9 +2860,9 @@ def create_mediumtext_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/mediumtext' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -2928,11 +2931,11 @@ def update_mediumtext_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/mediumtext/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -2993,9 +2996,9 @@ def create_point_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/point' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -3060,11 +3063,11 @@ def update_point_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/point/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -3126,9 +3129,9 @@ def create_polygon_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/polygon' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -3193,11 +3196,11 @@ def update_polygon_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/polygon/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -3268,9 +3271,9 @@ def create_relationship_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/relationship' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if related_table_id is None: raise AppwriteException('Missing required parameter: "related_table_id"') @@ -3302,6 +3305,69 @@ def create_relationship_column( return self._parse_response(response, model=ColumnRelationship) + def update_relationship_column( + self, + database_id: str, + table_id: str, + key: str, + on_delete: Optional[RelationMutate] = None, + new_key: Optional[str] = None, + ) -> ColumnRelationship: + """ + Update relationship column. [Learn more about relationship columns](https://appwrite.io/docs/databases-relationships#relationship-columns). + + Parameters + ---------- + database_id : str + Database ID. + table_id : str + Table ID. + key : str + Column Key. + on_delete : Optional[RelationMutate] + Delete constraint. Possible values are: cascade, restrict, setNull. + new_key : Optional[str] + New Column Key. + Returns + ------- + ColumnRelationship + API response as a typed Pydantic model + + Raises + ------ + AppwriteException + If API request fails + """ + + api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/relationship/{key}' + api_params = {} + if database_id is None or database_id == '': + raise AppwriteException('Missing required parameter: "database_id"') + if table_id is None or table_id == '': + raise AppwriteException('Missing required parameter: "table_id"') + if key is None or key == '': + raise AppwriteException('Missing required parameter: "key"') + api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) + api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) + api_path = api_path.replace('{key}', str(self._normalize_value(key))) + if on_delete is not None: + api_params['onDelete'] = self._normalize_value(on_delete) + if new_key is not None: + api_params['newKey'] = self._normalize_value(new_key) + + response = self.client.call( + 'patch', + api_path, + { + 'X-Appwrite-Project': self.client.get_config('project'), + 'content-type': 'application/json', + 'accept': 'application/json', + }, + api_params, + ) + + return self._parse_response(response, model=ColumnRelationship) + @deprecated("This API has been deprecated since 1.9.0. Please use `tablesDB.create_text_column` instead.") def create_string_column( self, @@ -3350,9 +3416,9 @@ def create_string_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/string' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -3430,11 +3496,11 @@ def update_string_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/string/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -3503,9 +3569,9 @@ def create_text_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/text' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -3574,11 +3640,11 @@ def update_text_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/text/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -3642,9 +3708,9 @@ def create_url_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/url' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -3711,11 +3777,11 @@ def update_url_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/url/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -3785,9 +3851,9 @@ def create_varchar_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/varchar' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -3862,11 +3928,11 @@ def update_varchar_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/varchar/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') if required is None: raise AppwriteException('Missing required parameter: "required"') @@ -3900,6 +3966,7 @@ def get_column( key: str, ) -> Union[ ColumnBoolean, + ColumnBigint, ColumnInteger, ColumnFloat, ColumnEmail, @@ -3908,6 +3975,13 @@ def get_column( ColumnIp, ColumnDatetime, ColumnRelationship, + ColumnPoint, + ColumnLine, + ColumnPolygon, + ColumnVarchar, + ColumnText, + ColumnMediumtext, + ColumnLongtext, ColumnString, ]: """ @@ -3923,7 +3997,7 @@ def get_column( Column Key. Returns ------- - Union[ColumnBoolean, ColumnInteger, ColumnFloat, ColumnEmail, ColumnEnum, ColumnUrl, ColumnIp, ColumnDatetime, ColumnRelationship, ColumnString] + Union[ColumnBoolean, ColumnBigint, ColumnInteger, ColumnFloat, ColumnEmail, ColumnEnum, ColumnUrl, ColumnIp, ColumnDatetime, ColumnRelationship, ColumnPoint, ColumnLine, ColumnPolygon, ColumnVarchar, ColumnText, ColumnMediumtext, ColumnLongtext, ColumnString] API response as one of the typed response models Raises @@ -3934,11 +4008,11 @@ def get_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -3971,6 +4045,9 @@ def get_column( if response.get('type') == 'boolean': return self._parse_response(response, model=ColumnBoolean) + if response.get('type') == 'bigint': + return self._parse_response(response, model=ColumnBigint) + if response.get('type') == 'integer': return self._parse_response(response, model=ColumnInteger) @@ -3983,6 +4060,27 @@ def get_column( if response.get('type') == 'relationship': return self._parse_response(response, model=ColumnRelationship) + if response.get('type') == 'point': + return self._parse_response(response, model=ColumnPoint) + + if response.get('type') == 'linestring': + return self._parse_response(response, model=ColumnLine) + + if response.get('type') == 'polygon': + return self._parse_response(response, model=ColumnPolygon) + + if response.get('type') == 'varchar': + return self._parse_response(response, model=ColumnVarchar) + + if response.get('type') == 'text': + return self._parse_response(response, model=ColumnText) + + if response.get('type') == 'mediumtext': + return self._parse_response(response, model=ColumnMediumtext) + + if response.get('type') == 'longtext': + return self._parse_response(response, model=ColumnLongtext) + if response.get('type') == 'string': return self._parse_response(response, model=ColumnString) @@ -4018,11 +4116,11 @@ def delete_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -4031,68 +4129,6 @@ def delete_column( response = self.client.call( 'delete', api_path, - { - 'X-Appwrite-Project': self.client.get_config('project'), - 'content-type': 'application/json', - }, - api_params, - ) - - return response - - def update_relationship_column( - self, - database_id: str, - table_id: str, - key: str, - on_delete: Optional[RelationMutate] = None, - new_key: Optional[str] = None, - ) -> ColumnRelationship: - """ - Update relationship column. [Learn more about relationship columns](https://appwrite.io/docs/databases-relationships#relationship-columns). - - Parameters - ---------- - database_id : str - Database ID. - table_id : str - Table ID. - key : str - Column Key. - on_delete : Optional[RelationMutate] - Delete constraint. Possible values are: cascade, restrict, setNull. - new_key : Optional[str] - New Column Key. - Returns - ------- - ColumnRelationship - API response as a typed Pydantic model - - Raises - ------ - AppwriteException - If API request fails - """ - - api_path = '/tablesdb/{databaseId}/tables/{tableId}/columns/{key}/relationship' - api_params = {} - if database_id is None: - raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: - raise AppwriteException('Missing required parameter: "table_id"') - if key is None: - raise AppwriteException('Missing required parameter: "key"') - api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) - api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) - api_path = api_path.replace('{key}', str(self._normalize_value(key))) - if on_delete is not None: - api_params['onDelete'] = self._normalize_value(on_delete) - if new_key is not None: - api_params['newKey'] = self._normalize_value(new_key) - - response = self.client.call( - 'patch', - api_path, { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', @@ -4101,7 +4137,7 @@ def update_relationship_column( api_params, ) - return self._parse_response(response, model=ColumnRelationship) + return response def list_indexes( self, @@ -4136,9 +4172,9 @@ def list_indexes( api_path = '/tablesdb/{databaseId}/tables/{tableId}/indexes' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -4171,7 +4207,7 @@ def create_index( ) -> ColumnIndex: """ Creates an index on the columns listed. Your index should include all the columns you will query in a single request. - Type can be `key`, `fulltext`, or `unique`. + Type can be `key`, `fulltext`, `unique`, `spatial`, or `trigram`. `trigram` is only available on PostgreSQL and lets `contains`, `startsWith`, and `endsWith` queries on string columns use an index. Parameters ---------- @@ -4202,9 +4238,9 @@ def create_index( api_path = '/tablesdb/{databaseId}/tables/{tableId}/indexes' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -4265,11 +4301,11 @@ def get_index( api_path = '/tablesdb/{databaseId}/tables/{tableId}/indexes/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -4317,11 +4353,11 @@ def delete_index( api_path = '/tablesdb/{databaseId}/tables/{tableId}/indexes/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -4333,6 +4369,7 @@ def delete_index( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -4382,9 +4419,9 @@ def list_rows( api_path = '/tablesdb/{databaseId}/tables/{tableId}/rows' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -4452,9 +4489,9 @@ def create_row( api_path = '/tablesdb/{databaseId}/tables/{tableId}/rows' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if row_id is None: raise AppwriteException('Missing required parameter: "row_id"') @@ -4519,9 +4556,9 @@ def create_rows( api_path = '/tablesdb/{databaseId}/tables/{tableId}/rows' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if rows is None: raise AppwriteException('Missing required parameter: "rows"') @@ -4581,9 +4618,9 @@ def upsert_rows( api_path = '/tablesdb/{databaseId}/tables/{tableId}/rows' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') if rows is None: raise AppwriteException('Missing required parameter: "rows"') @@ -4646,9 +4683,9 @@ def update_rows( api_path = '/tablesdb/{databaseId}/tables/{tableId}/rows' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -4709,9 +4746,9 @@ def delete_rows( api_path = '/tablesdb/{databaseId}/tables/{tableId}/rows' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -4773,11 +4810,11 @@ def get_row( api_path = '/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if row_id is None: + if row_id is None or row_id == '': raise AppwriteException('Missing required parameter: "row_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -4842,11 +4879,11 @@ def upsert_row( api_path = '/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if row_id is None: + if row_id is None or row_id == '': raise AppwriteException('Missing required parameter: "row_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -4914,11 +4951,11 @@ def update_row( api_path = '/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if row_id is None: + if row_id is None or row_id == '': raise AppwriteException('Missing required parameter: "row_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -4976,11 +5013,11 @@ def delete_row( api_path = '/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if row_id is None: + if row_id is None or row_id == '': raise AppwriteException('Missing required parameter: "row_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -4994,6 +5031,7 @@ def delete_row( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -5046,13 +5084,13 @@ def decrement_row_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}/{column}/decrement' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if row_id is None: + if row_id is None or row_id == '': raise AppwriteException('Missing required parameter: "row_id"') - if column is None: + if column is None or column == '': raise AppwriteException('Missing required parameter: "column"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) @@ -5124,13 +5162,13 @@ def increment_row_column( api_path = '/tablesdb/{databaseId}/tables/{tableId}/rows/{rowId}/{column}/increment' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if table_id is None: + if table_id is None or table_id == '': raise AppwriteException('Missing required parameter: "table_id"') - if row_id is None: + if row_id is None or row_id == '': raise AppwriteException('Missing required parameter: "row_id"') - if column is None: + if column is None or column == '': raise AppwriteException('Missing required parameter: "column"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{tableId}', str(self._normalize_value(table_id))) diff --git a/appwrite/services/teams.py b/appwrite/services/teams.py index 48092675..00a695d3 100644 --- a/appwrite/services/teams.py +++ b/appwrite/services/teams.py @@ -89,7 +89,7 @@ def create( name : str Team name. Max length: 128 chars. roles : Optional[List[str]] - Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of 100 roles are allowed, each 32 characters long. + Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https://appwrite.io/docs/permissions). Maximum of 100 roles are allowed, each 81 characters long. model_type : Type[T], optional Pydantic model class for the user-defined data. Defaults to dict for backward compatibility. @@ -156,7 +156,7 @@ def get( api_path = '/teams/{teamId}' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') api_path = api_path.replace('{teamId}', str(self._normalize_value(team_id))) @@ -203,7 +203,7 @@ def update_name( api_path = '/teams/{teamId}' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -247,7 +247,7 @@ def delete( api_path = '/teams/{teamId}' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') api_path = api_path.replace('{teamId}', str(self._normalize_value(team_id))) @@ -257,6 +257,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -293,7 +294,7 @@ def list_installations( api_path = '/teams/{teamId}/installations' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') api_path = api_path.replace('{teamId}', str(self._normalize_value(team_id))) if queries is not None: @@ -343,7 +344,7 @@ def create_installation( api_path = '/teams/{teamId}/installations' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') if app_id is None: raise AppwriteException('Missing required parameter: "app_id"') @@ -392,9 +393,9 @@ def get_installation( api_path = '/teams/{teamId}/installations/{installationId}' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') - if installation_id is None: + if installation_id is None or installation_id == '': raise AppwriteException('Missing required parameter: "installation_id"') api_path = api_path.replace('{teamId}', str(self._normalize_value(team_id))) api_path = api_path.replace('{installationId}', str(self._normalize_value(installation_id))) @@ -441,9 +442,9 @@ def update_installation( api_path = '/teams/{teamId}/installations/{installationId}' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') - if installation_id is None: + if installation_id is None or installation_id == '': raise AppwriteException('Missing required parameter: "installation_id"') api_path = api_path.replace('{teamId}', str(self._normalize_value(team_id))) api_path = api_path.replace('{installationId}', str(self._normalize_value(installation_id))) @@ -490,9 +491,9 @@ def delete_installation( api_path = '/teams/{teamId}/installations/{installationId}' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') - if installation_id is None: + if installation_id is None or installation_id == '': raise AppwriteException('Missing required parameter: "installation_id"') api_path = api_path.replace('{teamId}', str(self._normalize_value(team_id))) api_path = api_path.replace('{installationId}', str(self._normalize_value(installation_id))) @@ -543,7 +544,7 @@ def list_memberships( api_path = '/teams/{teamId}/memberships' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') api_path = api_path.replace('{teamId}', str(self._normalize_value(team_id))) if queries is not None: @@ -616,7 +617,7 @@ def create_membership( api_path = '/teams/{teamId}/memberships' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') if roles is None: raise AppwriteException('Missing required parameter: "roles"') @@ -675,9 +676,9 @@ def get_membership( api_path = '/teams/{teamId}/memberships/{membershipId}' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') - if membership_id is None: + if membership_id is None or membership_id == '': raise AppwriteException('Missing required parameter: "membership_id"') api_path = api_path.replace('{teamId}', str(self._normalize_value(team_id))) api_path = api_path.replace('{membershipId}', str(self._normalize_value(membership_id))) @@ -724,9 +725,9 @@ def update_membership( api_path = '/teams/{teamId}/memberships/{membershipId}' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') - if membership_id is None: + if membership_id is None or membership_id == '': raise AppwriteException('Missing required parameter: "membership_id"') if roles is None: raise AppwriteException('Missing required parameter: "roles"') @@ -774,9 +775,9 @@ def delete_membership( api_path = '/teams/{teamId}/memberships/{membershipId}' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') - if membership_id is None: + if membership_id is None or membership_id == '': raise AppwriteException('Missing required parameter: "membership_id"') api_path = api_path.replace('{teamId}', str(self._normalize_value(team_id))) api_path = api_path.replace('{membershipId}', str(self._normalize_value(membership_id))) @@ -787,6 +788,7 @@ def delete_membership( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -828,9 +830,9 @@ def update_membership_status( api_path = '/teams/{teamId}/memberships/{membershipId}/status' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') - if membership_id is None: + if membership_id is None or membership_id == '': raise AppwriteException('Missing required parameter: "membership_id"') if user_id is None: raise AppwriteException('Missing required parameter: "user_id"') @@ -882,7 +884,7 @@ def get_prefs( api_path = '/teams/{teamId}/prefs' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') api_path = api_path.replace('{teamId}', str(self._normalize_value(team_id))) @@ -929,7 +931,7 @@ def update_prefs( api_path = '/teams/{teamId}/prefs' api_params = {} - if team_id is None: + if team_id is None or team_id == '': raise AppwriteException('Missing required parameter: "team_id"') if prefs is None: raise AppwriteException('Missing required parameter: "prefs"') diff --git a/appwrite/services/tokens.py b/appwrite/services/tokens.py index d3c9eae4..b3edf492 100644 --- a/appwrite/services/tokens.py +++ b/appwrite/services/tokens.py @@ -45,9 +45,9 @@ def list( api_path = '/tokens/buckets/{bucketId}/files/{fileId}' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') - if file_id is None: + if file_id is None or file_id == '': raise AppwriteException('Missing required parameter: "file_id"') api_path = api_path.replace('{bucketId}', str(self._normalize_value(bucket_id))) api_path = api_path.replace('{fileId}', str(self._normalize_value(file_id))) @@ -98,9 +98,9 @@ def create_file_token( api_path = '/tokens/buckets/{bucketId}/files/{fileId}' api_params = {} - if bucket_id is None: + if bucket_id is None or bucket_id == '': raise AppwriteException('Missing required parameter: "bucket_id"') - if file_id is None: + if file_id is None or file_id == '': raise AppwriteException('Missing required parameter: "file_id"') api_path = api_path.replace('{bucketId}', str(self._normalize_value(bucket_id))) api_path = api_path.replace('{fileId}', str(self._normalize_value(file_id))) @@ -144,7 +144,7 @@ def get( api_path = '/tokens/{tokenId}' api_params = {} - if token_id is None: + if token_id is None or token_id == '': raise AppwriteException('Missing required parameter: "token_id"') api_path = api_path.replace('{tokenId}', str(self._normalize_value(token_id))) @@ -187,7 +187,7 @@ def update( api_path = '/tokens/{tokenId}' api_params = {} - if token_id is None: + if token_id is None or token_id == '': raise AppwriteException('Missing required parameter: "token_id"') api_path = api_path.replace('{tokenId}', str(self._normalize_value(token_id))) if expire is not None: @@ -230,7 +230,7 @@ def delete( api_path = '/tokens/{tokenId}' api_params = {} - if token_id is None: + if token_id is None or token_id == '': raise AppwriteException('Missing required parameter: "token_id"') api_path = api_path.replace('{tokenId}', str(self._normalize_value(token_id))) @@ -240,6 +240,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) diff --git a/appwrite/services/users.py b/appwrite/services/users.py index a2fb834b..6e89654b 100644 --- a/appwrite/services/users.py +++ b/appwrite/services/users.py @@ -8,7 +8,6 @@ from ..models.identity_list import IdentityList from ..enums.password_hash import PasswordHash from ..models.jwt import Jwt -from ..models.log_list import LogList from ..models.membership_list import MembershipList from ..enums.authenticator_type import AuthenticatorType from ..models.mfa_challenge_secret import MfaChallengeSecret @@ -45,7 +44,7 @@ def list( Parameters ---------- queries : Optional[List[str]] - Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels, impersonator, accessedAt + Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, passwordPwned, labels, impersonator, accessedAt search : Optional[str] Search term to filter your list results. Max length: 256 chars. total : Optional[bool] @@ -347,7 +346,7 @@ def delete_identity( api_path = '/users/identities/{identityId}' api_params = {} - if identity_id is None: + if identity_id is None or identity_id == '': raise AppwriteException('Missing required parameter: "identity_id"') api_path = api_path.replace('{identityId}', str(self._normalize_value(identity_id))) @@ -357,6 +356,7 @@ def delete_identity( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -754,7 +754,7 @@ def get( api_path = '/users/{userId}' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) @@ -794,7 +794,7 @@ def delete( api_path = '/users/{userId}' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) @@ -804,6 +804,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -841,7 +842,7 @@ def update_email( api_path = '/users/{userId}/email' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if email is None: raise AppwriteException('Missing required parameter: "email"') @@ -868,7 +869,7 @@ def update_impersonator( model_type: Type[T] = dict, ) -> User[T]: """ - Enable or disable whether a user can impersonate other users. When impersonation headers are used, the request runs as the target user for API behavior, while internal audit logs still attribute the action to the original impersonator and store the impersonated target details only in internal audit payload data. + Enable or disable whether a user can impersonate other users. When impersonation headers are used, the request runs as the target user for API behavior, while internal audit logs still attribute the action to the original impersonator and store the impersonated target details only in internal audit payload data. Account endpoints are read-only while impersonating: they report the target's account, and anything that would change it is refused, so an impersonator cannot alter the target's credentials or delete their account. Parameters ---------- @@ -892,7 +893,7 @@ def update_impersonator( api_path = '/users/{userId}/impersonator' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if impersonator is None: raise AppwriteException('Missing required parameter: "impersonator"') @@ -942,7 +943,7 @@ def create_jwt( api_path = '/users/{userId}/jwts' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) if session_id is not None: @@ -996,7 +997,7 @@ def update_labels( api_path = '/users/{userId}/labels' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if labels is None: raise AppwriteException('Missing required parameter: "labels"') @@ -1016,56 +1017,6 @@ def update_labels( return User.with_data(response, model_type) - def list_logs( - self, - user_id: str, - queries: Optional[List[str]] = None, - total: Optional[bool] = None, - ) -> LogList: - """ - Get the user activity logs list by its unique ID. - - Parameters - ---------- - user_id : str - User ID. - queries : Optional[List[str]] - Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Only supported methods are limit and offset - total : Optional[bool] - When set to false, the total count returned will be 0 and will not be calculated. - Returns - ------- - LogList - API response as a typed Pydantic model - - Raises - ------ - AppwriteException - If API request fails - """ - - api_path = '/users/{userId}/logs' - api_params = {} - if user_id is None: - raise AppwriteException('Missing required parameter: "user_id"') - api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) - if queries is not None: - api_params['queries'] = self._normalize_value(queries) - if total is not None: - api_params['total'] = self._normalize_value(total) - - response = self.client.call( - 'get', - api_path, - { - 'X-Appwrite-Project': self.client.get_config('project'), - 'accept': 'application/json', - }, - api_params, - ) - - return self._parse_response(response, model=LogList) - def list_memberships( self, user_id: str, @@ -1099,7 +1050,7 @@ def list_memberships( api_path = '/users/{userId}/memberships' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) if queries is not None: @@ -1152,7 +1103,7 @@ def update_mfa( api_path = '/users/{userId}/mfa' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if mfa is None: raise AppwriteException('Missing required parameter: "mfa"') @@ -1199,7 +1150,7 @@ def delete_mfa_authenticator( api_path = '/users/{userId}/mfa/authenticators/{type}' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if type is None: raise AppwriteException('Missing required parameter: "type"') @@ -1212,6 +1163,7 @@ def delete_mfa_authenticator( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -1245,9 +1197,9 @@ def get_mfa_challenge( api_path = '/users/{userId}/mfa/challenges/{challengeId}' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') - if challenge_id is None: + if challenge_id is None or challenge_id == '': raise AppwriteException('Missing required parameter: "challenge_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) api_path = api_path.replace('{challengeId}', str(self._normalize_value(challenge_id))) @@ -1288,7 +1240,7 @@ def list_mfa_factors( api_path = '/users/{userId}/mfa/factors' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) @@ -1328,7 +1280,7 @@ def get_mfa_recovery_codes( api_path = '/users/{userId}/mfa/recovery-codes' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) @@ -1368,7 +1320,7 @@ def update_mfa_recovery_codes( api_path = '/users/{userId}/mfa/recovery-codes' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) @@ -1409,7 +1361,7 @@ def create_mfa_recovery_codes( api_path = '/users/{userId}/mfa/recovery-codes' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) @@ -1457,7 +1409,7 @@ def update_name( api_path = '/users/{userId}/name' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -1704,7 +1656,7 @@ def update_password( api_path = '/users/{userId}/password' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if password is None: raise AppwriteException('Missing required parameter: "password"') @@ -1755,7 +1707,7 @@ def update_phone( api_path = '/users/{userId}/phone' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if number is None: raise AppwriteException('Missing required parameter: "number"') @@ -1803,7 +1755,7 @@ def get_prefs( api_path = '/users/{userId}/prefs' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) @@ -1850,7 +1802,7 @@ def update_prefs( api_path = '/users/{userId}/prefs' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if prefs is None: raise AppwriteException('Missing required parameter: "prefs"') @@ -1897,7 +1849,7 @@ def list_sessions( api_path = '/users/{userId}/sessions' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) if total is not None: @@ -1941,7 +1893,7 @@ def create_session( api_path = '/users/{userId}/sessions' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) @@ -1982,7 +1934,7 @@ def delete_sessions( api_path = '/users/{userId}/sessions' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) @@ -1992,6 +1944,7 @@ def delete_sessions( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -2025,9 +1978,9 @@ def delete_session( api_path = '/users/{userId}/sessions/{sessionId}' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') - if session_id is None: + if session_id is None or session_id == '': raise AppwriteException('Missing required parameter: "session_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) api_path = api_path.replace('{sessionId}', str(self._normalize_value(session_id))) @@ -2038,6 +1991,7 @@ def delete_session( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -2075,7 +2029,7 @@ def update_status( api_path = '/users/{userId}/status' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if status is None: raise AppwriteException('Missing required parameter: "status"') @@ -2125,7 +2079,7 @@ def list_targets( api_path = '/users/{userId}/targets' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) if queries is not None: @@ -2184,7 +2138,7 @@ def create_target( api_path = '/users/{userId}/targets' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if target_id is None: raise AppwriteException('Missing required parameter: "target_id"') @@ -2241,9 +2195,9 @@ def get_target( api_path = '/users/{userId}/targets/{targetId}' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') - if target_id is None: + if target_id is None or target_id == '': raise AppwriteException('Missing required parameter: "target_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) api_path = api_path.replace('{targetId}', str(self._normalize_value(target_id))) @@ -2296,9 +2250,9 @@ def update_target( api_path = '/users/{userId}/targets/{targetId}' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') - if target_id is None: + if target_id is None or target_id == '': raise AppwriteException('Missing required parameter: "target_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) api_path = api_path.replace('{targetId}', str(self._normalize_value(target_id))) @@ -2349,9 +2303,9 @@ def delete_target( api_path = '/users/{userId}/targets/{targetId}' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') - if target_id is None: + if target_id is None or target_id == '': raise AppwriteException('Missing required parameter: "target_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) api_path = api_path.replace('{targetId}', str(self._normalize_value(target_id))) @@ -2362,6 +2316,7 @@ def delete_target( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -2398,7 +2353,7 @@ def create_token( api_path = '/users/{userId}/tokens' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') api_path = api_path.replace('{userId}', str(self._normalize_value(user_id))) if length is not None: @@ -2450,7 +2405,7 @@ def update_email_verification( api_path = '/users/{userId}/verification' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if email_verification is None: raise AppwriteException('Missing required parameter: "email_verification"') @@ -2501,7 +2456,7 @@ def update_phone_verification( api_path = '/users/{userId}/verification/phone' api_params = {} - if user_id is None: + if user_id is None or user_id == '': raise AppwriteException('Missing required parameter: "user_id"') if phone_verification is None: raise AppwriteException('Missing required parameter: "phone_verification"') diff --git a/appwrite/services/vectors_db.py b/appwrite/services/vectors_db.py index a23ccb29..1cea0603 100644 --- a/appwrite/services/vectors_db.py +++ b/appwrite/services/vectors_db.py @@ -144,7 +144,7 @@ def list_specifications( self, ) -> DedicatedDatabaseSpecificationList: """ - List the dedicated database specifications available on the current plan. Each specification reports its resource limits, pricing, and whether it is enabled for the organization. + List the dedicated database specifications available on the current plan. Each specification reports its resource limits, its own prices and overage rates, and whether it is enabled for the organization. Returns ------- DedicatedDatabaseSpecificationList @@ -279,7 +279,7 @@ def get_transaction( api_path = '/vectorsdb/transactions/{transactionId}' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) @@ -325,7 +325,7 @@ def update_transaction( api_path = '/vectorsdb/transactions/{transactionId}' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) if commit is not None: @@ -370,7 +370,7 @@ def delete_transaction( api_path = '/vectorsdb/transactions/{transactionId}' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) @@ -380,6 +380,7 @@ def delete_transaction( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -413,7 +414,7 @@ def create_operations( api_path = '/vectorsdb/transactions/{transactionId}/operations' api_params = {} - if transaction_id is None: + if transaction_id is None or transaction_id == '': raise AppwriteException('Missing required parameter: "transaction_id"') api_path = api_path.replace('{transactionId}', str(self._normalize_value(transaction_id))) if operations is not None: @@ -456,7 +457,7 @@ def get( api_path = '/vectorsdb/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -511,7 +512,7 @@ def update( api_path = '/vectorsdb/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -563,7 +564,7 @@ def delete( api_path = '/vectorsdb/{databaseId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -573,6 +574,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -612,7 +614,7 @@ def list_collections( api_path = '/vectorsdb/{databaseId}/collections' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if queries is not None: @@ -676,7 +678,7 @@ def create_collection( api_path = '/vectorsdb/{databaseId}/collections' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') if collection_id is None: raise AppwriteException('Missing required parameter: "collection_id"') @@ -735,9 +737,9 @@ def get_collection( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -796,9 +798,9 @@ def update_collection( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -854,9 +856,9 @@ def delete_collection( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -867,6 +869,7 @@ def delete_collection( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -916,9 +919,9 @@ def list_documents( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -986,9 +989,9 @@ def create_document( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if document_id is None: raise AppwriteException('Missing required parameter: "document_id"') @@ -1053,9 +1056,9 @@ def create_documents( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if documents is None: raise AppwriteException('Missing required parameter: "documents"') @@ -1115,9 +1118,9 @@ def upsert_documents( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if documents is None: raise AppwriteException('Missing required parameter: "documents"') @@ -1180,9 +1183,9 @@ def update_documents( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1243,9 +1246,9 @@ def delete_documents( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/documents' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1310,9 +1313,9 @@ def create_query( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/documents/query' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1378,11 +1381,11 @@ def get_document( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/documents/{documentId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1447,11 +1450,11 @@ def upsert_document( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/documents/{documentId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1519,11 +1522,11 @@ def update_document( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/documents/{documentId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1581,11 +1584,11 @@ def delete_document( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/documents/{documentId}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if document_id is None: + if document_id is None or document_id == '': raise AppwriteException('Missing required parameter: "document_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1599,6 +1602,7 @@ def delete_document( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -1638,9 +1642,9 @@ def list_indexes( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/indexes' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1704,9 +1708,9 @@ def create_index( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/indexes' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') if key is None: raise AppwriteException('Missing required parameter: "key"') @@ -1767,11 +1771,11 @@ def get_index( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/indexes/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1819,11 +1823,11 @@ def delete_index( api_path = '/vectorsdb/{databaseId}/collections/{collectionId}/indexes/{key}' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') - if collection_id is None: + if collection_id is None or collection_id == '': raise AppwriteException('Missing required parameter: "collection_id"') - if key is None: + if key is None or key == '': raise AppwriteException('Missing required parameter: "key"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) api_path = api_path.replace('{collectionId}', str(self._normalize_value(collection_id))) @@ -1835,6 +1839,7 @@ def delete_index( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -1868,7 +1873,7 @@ def create_failover( api_path = '/vectorsdb/{databaseId}/failovers' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if target_replica_id is not None: @@ -1920,7 +1925,7 @@ def list_operations( api_path = '/vectorsdb/{databaseId}/operations' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) if status is not None: @@ -1966,7 +1971,7 @@ def get_replicas( api_path = '/vectorsdb/{databaseId}/replicas' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) @@ -2006,7 +2011,7 @@ def get_status( api_path = '/vectorsdb/{databaseId}/status' api_params = {} - if database_id is None: + if database_id is None or database_id == '': raise AppwriteException('Missing required parameter: "database_id"') api_path = api_path.replace('{databaseId}', str(self._normalize_value(database_id))) diff --git a/appwrite/services/webhooks.py b/appwrite/services/webhooks.py index 16674e2c..6caa4745 100644 --- a/appwrite/services/webhooks.py +++ b/appwrite/services/webhooks.py @@ -86,9 +86,9 @@ def create( tls : Optional[bool] Certificate verification, false for disabled or true for enabled. auth_username : Optional[str] - Webhook HTTP user. Max length: 256 chars. + Webhook HTTP user. Max length: 255 chars. auth_password : Optional[str] - Webhook HTTP password. Max length: 256 chars. + Webhook HTTP password. Max length: 2048 chars. secret : Optional[str] Webhook secret key. If not provided, a new key will be generated automatically. Key must be at least 8 characters long, and at max 256 characters. Returns @@ -164,7 +164,7 @@ def get( api_path = '/webhooks/{webhookId}' api_params = {} - if webhook_id is None: + if webhook_id is None or webhook_id == '': raise AppwriteException('Missing required parameter: "webhook_id"') api_path = api_path.replace('{webhookId}', str(self._normalize_value(webhook_id))) @@ -209,9 +209,9 @@ def update( tls : Optional[bool] Certificate verification, false for disabled or true for enabled. auth_username : Optional[str] - Webhook HTTP user. Max length: 256 chars. + Webhook HTTP user. Max length: 255 chars. auth_password : Optional[str] - Webhook HTTP password. Max length: 256 chars. + Webhook HTTP password. Max length: 2048 chars. Omit to keep the current password; it is cleared when the URL changes or TLS verification is disabled. Returns ------- Webhook @@ -225,7 +225,7 @@ def update( api_path = '/webhooks/{webhookId}' api_params = {} - if webhook_id is None: + if webhook_id is None or webhook_id == '': raise AppwriteException('Missing required parameter: "webhook_id"') if name is None: raise AppwriteException('Missing required parameter: "name"') @@ -283,7 +283,7 @@ def delete( api_path = '/webhooks/{webhookId}' api_params = {} - if webhook_id is None: + if webhook_id is None or webhook_id == '': raise AppwriteException('Missing required parameter: "webhook_id"') api_path = api_path.replace('{webhookId}', str(self._normalize_value(webhook_id))) @@ -293,6 +293,7 @@ def delete( { 'X-Appwrite-Project': self.client.get_config('project'), 'content-type': 'application/json', + 'accept': 'application/json', }, api_params, ) @@ -326,7 +327,7 @@ def update_secret( api_path = '/webhooks/{webhookId}/secret' api_params = {} - if webhook_id is None: + if webhook_id is None or webhook_id == '': raise AppwriteException('Missing required parameter: "webhook_id"') api_path = api_path.replace('{webhookId}', str(self._normalize_value(webhook_id))) if secret is not None: diff --git a/appwrite/topic.py b/appwrite/topic.py new file mode 100644 index 00000000..99253d20 --- /dev/null +++ b/appwrite/topic.py @@ -0,0 +1,67 @@ +from types import MethodType + + +def _levels_of(levels): + """ + Validate the levels passed to `path()`: a non-empty list of non-empty strings, none holding + the level separator `/` or the MQTT wildcards `+` and `#`. + """ + if not isinstance(levels, (list, tuple)): + raise TypeError("path() expects an array, e.g. path(['user'])") + if len(levels) == 0: + raise ValueError("path() needs at least one level") + for index, level in enumerate(levels): + if not isinstance(level, str): + kind = "null" if level is None else type(level).__name__ + raise TypeError(f"level at index {index} must be a string, got {kind}") + if level == "": + raise ValueError(f"empty level at index {index}") + if "/" in level: + parts = ", ".join(f"'{part}'" for part in level.split("/")) + raise ValueError(f'"{level}" contains "/", split it: path([{parts}])') + if "+" in level: + raise ValueError(f'"{level}" contains "+", not allowed in a topic') + if "#" in level: + raise ValueError(f'"{level}" contains "#", not allowed in a topic') + if "\0" in level: + raise ValueError(f"level at index {index} contains a NUL character") + return tuple(levels) + + +class _builder: + """ + Bind a Topic method to the instance it is read from, or to an empty topic when it is read + from the class, so `Topic.path([...])` starts a topic and `topic.path([...])` extends one. + """ + + def __init__(self, func): + self.__func__ = func + self.__doc__ = func.__doc__ + + def __get__(self, instance, owner=None): + target = instance if instance is not None else owner(()) + return MethodType(self.__func__, target) + + +class Topic: + """ + Helper to build MQTT topics for `Push`, level by level. + + Topic.path(['user', user_id, 'notification']) # "user/123/notification" + Topic.path(['org', org_id]).path(['logs']) # "org/42/logs" + """ + + def __init__(self, levels): + # Internal: build topics with `Topic.path()`. + self._levels = tuple(levels) + + @_builder + def path(self, levels): + """Start a topic with the given levels, or append them, e.g. `Topic.path(['user', user_id])`.""" + return Topic(self._levels + _levels_of(levels)) + + def __str__(self): + return "/".join(self._levels) + + def __repr__(self): + return f"Topic({str(self)!r})" diff --git a/docs/examples/account/create-mfa-authenticator.md b/docs/examples/account/create-mfa-authenticator.md index 468011b2..745a0314 100644 --- a/docs/examples/account/create-mfa-authenticator.md +++ b/docs/examples/account/create-mfa-authenticator.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.account import Account from appwrite.models import MfaType -from appwrite.enums import AuthenticatorType +from appwrite.enums.authenticator_type import AuthenticatorType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/account/create-mfa-challenge.md b/docs/examples/account/create-mfa-challenge.md index f31797a4..e26d4e9b 100644 --- a/docs/examples/account/create-mfa-challenge.md +++ b/docs/examples/account/create-mfa-challenge.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.account import Account from appwrite.models import MfaChallenge -from appwrite.enums import AuthenticationFactor +from appwrite.enums.authentication_factor import AuthenticationFactor client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/account/create-o-auth-2-token.md b/docs/examples/account/create-o-auth-2-token.md index cae5a66e..e21fb47d 100644 --- a/docs/examples/account/create-o-auth-2-token.md +++ b/docs/examples/account/create-o-auth-2-token.md @@ -1,7 +1,7 @@ ```python from appwrite.client import Client from appwrite.services.account import Account -from appwrite.enums import OAuthProvider +from appwrite.enums.o_auth_provider import OAuthProvider client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/account/delete-mfa-authenticator.md b/docs/examples/account/delete-mfa-authenticator.md index faeccb8b..bc5219a0 100644 --- a/docs/examples/account/delete-mfa-authenticator.md +++ b/docs/examples/account/delete-mfa-authenticator.md @@ -1,7 +1,7 @@ ```python from appwrite.client import Client from appwrite.services.account import Account -from appwrite.enums import AuthenticatorType +from appwrite.enums.authenticator_type import AuthenticatorType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/account/list-logs.md b/docs/examples/account/list-logs.md deleted file mode 100644 index 3f0a3b55..00000000 --- a/docs/examples/account/list-logs.md +++ /dev/null @@ -1,19 +0,0 @@ -```python -from appwrite.client import Client -from appwrite.services.account import Account -from appwrite.models import LogList - -client = Client() -client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_project('') # Your project ID -client.set_session('') # The user session to authenticate with - -account = Account(client) - -result: LogList = account.list_logs( - queries = [], # optional - total = False # optional -) - -print(result.model_dump()) -``` diff --git a/docs/examples/account/update-mfa-authenticator.md b/docs/examples/account/update-mfa-authenticator.md index e7040b0a..60204b9d 100644 --- a/docs/examples/account/update-mfa-authenticator.md +++ b/docs/examples/account/update-mfa-authenticator.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.account import Account from appwrite.models import User -from appwrite.enums import AuthenticatorType +from appwrite.enums.authenticator_type import AuthenticatorType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/avatars/get-browser.md b/docs/examples/avatars/get-browser.md index 3c950dbb..622244be 100644 --- a/docs/examples/avatars/get-browser.md +++ b/docs/examples/avatars/get-browser.md @@ -1,7 +1,7 @@ ```python from appwrite.client import Client from appwrite.services.avatars import Avatars -from appwrite.enums import Browser +from appwrite.enums.browser import Browser client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/avatars/get-credit-card.md b/docs/examples/avatars/get-credit-card.md index 8ef04f63..8888b752 100644 --- a/docs/examples/avatars/get-credit-card.md +++ b/docs/examples/avatars/get-credit-card.md @@ -1,7 +1,7 @@ ```python from appwrite.client import Client from appwrite.services.avatars import Avatars -from appwrite.enums import CreditCard +from appwrite.enums.credit_card import CreditCard client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/avatars/get-flag.md b/docs/examples/avatars/get-flag.md index f97b20dd..c8b628d8 100644 --- a/docs/examples/avatars/get-flag.md +++ b/docs/examples/avatars/get-flag.md @@ -1,7 +1,7 @@ ```python from appwrite.client import Client from appwrite.services.avatars import Avatars -from appwrite.enums import Flag +from appwrite.enums.flag import Flag client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/avatars/get-screenshot.md b/docs/examples/avatars/get-screenshot.md index cf7f9a6b..7e39b59b 100644 --- a/docs/examples/avatars/get-screenshot.md +++ b/docs/examples/avatars/get-screenshot.md @@ -1,10 +1,10 @@ ```python from appwrite.client import Client from appwrite.services.avatars import Avatars -from appwrite.enums import BrowserTheme -from appwrite.enums import Timezone -from appwrite.enums import BrowserPermission -from appwrite.enums import ImageFormat +from appwrite.enums.browser_theme import BrowserTheme +from appwrite.enums.timezone import Timezone +from appwrite.enums.browser_permission import BrowserPermission +from appwrite.enums.image_format import ImageFormat client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -16,8 +16,7 @@ avatars = Avatars(client) result: bytes = avatars.get_screenshot( url = 'https://example.com', headers = { - "Authorization": "Bearer token123", - "X-Custom-Header": "value" + "Accept-Language": "en-US,en;q=0.9" }, # optional viewport_width = 1920, # optional viewport_height = 1080, # optional diff --git a/docs/examples/backups/create-archive.md b/docs/examples/backups/create-archive.md index 77264469..6d25a93b 100644 --- a/docs/examples/backups/create-archive.md +++ b/docs/examples/backups/create-archive.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.backups import Backups from appwrite.models import BackupArchive -from appwrite.enums import BackupServices +from appwrite.enums.backup_services import BackupServices client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/backups/create-policy.md b/docs/examples/backups/create-policy.md index bf24e87a..a100d80e 100644 --- a/docs/examples/backups/create-policy.md +++ b/docs/examples/backups/create-policy.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.backups import Backups from appwrite.models import BackupPolicy -from appwrite.enums import BackupServices +from appwrite.enums.backup_services import BackupServices client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/backups/create-restoration.md b/docs/examples/backups/create-restoration.md index e2966caa..0c116884 100644 --- a/docs/examples/backups/create-restoration.md +++ b/docs/examples/backups/create-restoration.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.backups import Backups from appwrite.models import BackupRestoration -from appwrite.enums import BackupServices +from appwrite.enums.backup_services import BackupServices client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/databases/create-documents.md b/docs/examples/databases/create-documents.md index a1df96a9..13e7b94f 100644 --- a/docs/examples/databases/create-documents.md +++ b/docs/examples/databases/create-documents.md @@ -13,7 +13,16 @@ databases = Databases(client) result: DocumentList = databases.create_documents( database_id = '', collection_id = '', - documents = [], + documents = [ + { + "$id": "example1", + "username": "walter.obrien", + "email": "walter.obrien@example.com", + "fullName": "Walter O'Brien", + "age": 30, + "isAdmin": false + } + ], transaction_id = '' # optional ) diff --git a/docs/examples/databases/create-index.md b/docs/examples/databases/create-index.md index 71c694f1..8733b72a 100644 --- a/docs/examples/databases/create-index.md +++ b/docs/examples/databases/create-index.md @@ -2,8 +2,8 @@ from appwrite.client import Client from appwrite.services.databases import Databases from appwrite.models import Index -from appwrite.enums import DatabasesIndexType -from appwrite.enums import OrderBy +from appwrite.enums.databases_index_type import DatabasesIndexType +from appwrite.enums.order_by import OrderBy client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -17,7 +17,7 @@ result: Index = databases.create_index( collection_id = '', key = '', type = DatabasesIndexType.KEY, - attributes = [], + attributes = ["username"], orders = [OrderBy.ASC], # optional lengths = [] # optional ) diff --git a/docs/examples/databases/create-relationship-attribute.md b/docs/examples/databases/create-relationship-attribute.md index 81959496..48821cac 100644 --- a/docs/examples/databases/create-relationship-attribute.md +++ b/docs/examples/databases/create-relationship-attribute.md @@ -2,8 +2,8 @@ from appwrite.client import Client from appwrite.services.databases import Databases from appwrite.models import AttributeRelationship -from appwrite.enums import RelationshipType -from appwrite.enums import RelationMutate +from appwrite.enums.relationship_type import RelationshipType +from appwrite.enums.relation_mutate import RelationMutate client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/databases/delete-documents.md b/docs/examples/databases/delete-documents.md index d410bdef..21a2a214 100644 --- a/docs/examples/databases/delete-documents.md +++ b/docs/examples/databases/delete-documents.md @@ -13,7 +13,7 @@ databases = Databases(client) result: DocumentList = databases.delete_documents( database_id = '', collection_id = '', - queries = [], # optional + queries = ["{\"method\":\"equal\", \"attribute\":\"$id\", \"values\":[\"\"]}"], # optional transaction_id = '' # optional ) diff --git a/docs/examples/databases/get-attribute.md b/docs/examples/databases/get-attribute.md index 880a5872..fdcc23da 100644 --- a/docs/examples/databases/get-attribute.md +++ b/docs/examples/databases/get-attribute.md @@ -2,6 +2,7 @@ from appwrite.client import Client from appwrite.services.databases import Databases from appwrite.models import AttributeBoolean +from appwrite.models import AttributeBigint from appwrite.models import AttributeInteger from appwrite.models import AttributeFloat from appwrite.models import AttributeEmail @@ -10,6 +11,13 @@ from appwrite.models import AttributeUrl from appwrite.models import AttributeIp from appwrite.models import AttributeDatetime from appwrite.models import AttributeRelationship +from appwrite.models import AttributePoint +from appwrite.models import AttributeLine +from appwrite.models import AttributePolygon +from appwrite.models import AttributeVarchar +from appwrite.models import AttributeText +from appwrite.models import AttributeMediumtext +from appwrite.models import AttributeLongtext from appwrite.models import AttributeString from typing import Union @@ -20,7 +28,7 @@ client.set_key('') # Your secret API key databases = Databases(client) -result: Union[AttributeBoolean, AttributeInteger, AttributeFloat, AttributeEmail, AttributeEnum, AttributeUrl, AttributeIp, AttributeDatetime, AttributeRelationship, AttributeString] = databases.get_attribute( +result: Union[AttributeBoolean, AttributeBigint, AttributeInteger, AttributeFloat, AttributeEmail, AttributeEnum, AttributeUrl, AttributeIp, AttributeDatetime, AttributeRelationship, AttributePoint, AttributeLine, AttributePolygon, AttributeVarchar, AttributeText, AttributeMediumtext, AttributeLongtext, AttributeString] = databases.get_attribute( database_id = '', collection_id = '', key = '' diff --git a/docs/examples/databases/update-relationship-attribute.md b/docs/examples/databases/update-relationship-attribute.md index a507aca1..cc328d63 100644 --- a/docs/examples/databases/update-relationship-attribute.md +++ b/docs/examples/databases/update-relationship-attribute.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.databases import Databases from appwrite.models import AttributeRelationship -from appwrite.enums import RelationMutate +from appwrite.enums.relation_mutate import RelationMutate client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/databases/upsert-documents.md b/docs/examples/databases/upsert-documents.md index 5039ccb0..ae28f031 100644 --- a/docs/examples/databases/upsert-documents.md +++ b/docs/examples/databases/upsert-documents.md @@ -13,7 +13,16 @@ databases = Databases(client) result: DocumentList = databases.upsert_documents( database_id = '', collection_id = '', - documents = [], + documents = [ + { + "$id": "example1", + "username": "walter.obrien", + "email": "walter.obrien@example.com", + "fullName": "Walter O'Brien", + "age": 30, + "isAdmin": false + } + ], transaction_id = '' # optional ) diff --git a/docs/examples/documentsdb/create-documents.md b/docs/examples/documentsdb/create-documents.md index 2b15e560..7f470a36 100644 --- a/docs/examples/documentsdb/create-documents.md +++ b/docs/examples/documentsdb/create-documents.md @@ -13,7 +13,16 @@ documents_db = DocumentsDB(client) result: DocumentList = documents_db.create_documents( database_id = '', collection_id = '', - documents = [], + documents = [ + { + "$id": "example1", + "username": "walter.obrien", + "email": "walter.obrien@example.com", + "fullName": "Walter O'Brien", + "age": 30, + "isAdmin": false + } + ], transaction_id = '' # optional ) diff --git a/docs/examples/documentsdb/create-index.md b/docs/examples/documentsdb/create-index.md index 34a36dc8..51eea435 100644 --- a/docs/examples/documentsdb/create-index.md +++ b/docs/examples/documentsdb/create-index.md @@ -2,8 +2,8 @@ from appwrite.client import Client from appwrite.services.documents_db import DocumentsDB from appwrite.models import Index -from appwrite.enums import DocumentsDBIndexType -from appwrite.enums import OrderBy +from appwrite.enums.documents_db_index_type import DocumentsDBIndexType +from appwrite.enums.order_by import OrderBy client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -17,7 +17,7 @@ result: Index = documents_db.create_index( collection_id = '', key = '', type = DocumentsDBIndexType.KEY, - attributes = [], + attributes = ["username"], orders = [OrderBy.ASC], # optional lengths = [] # optional ) diff --git a/docs/examples/documentsdb/delete-documents.md b/docs/examples/documentsdb/delete-documents.md index 8bc343de..4b127c79 100644 --- a/docs/examples/documentsdb/delete-documents.md +++ b/docs/examples/documentsdb/delete-documents.md @@ -13,7 +13,7 @@ documents_db = DocumentsDB(client) result: DocumentList = documents_db.delete_documents( database_id = '', collection_id = '', - queries = [], # optional + queries = ["{\"method\":\"equal\", \"attribute\":\"$id\", \"values\":[\"\"]}"], # optional transaction_id = '' # optional ) diff --git a/docs/examples/documentsdb/upsert-documents.md b/docs/examples/documentsdb/upsert-documents.md index d98b227c..f1613df1 100644 --- a/docs/examples/documentsdb/upsert-documents.md +++ b/docs/examples/documentsdb/upsert-documents.md @@ -13,7 +13,16 @@ documents_db = DocumentsDB(client) result: DocumentList = documents_db.upsert_documents( database_id = '', collection_id = '', - documents = [], + documents = [ + { + "$id": "example1", + "username": "walter.obrien", + "email": "walter.obrien@example.com", + "fullName": "Walter O'Brien", + "age": 30, + "isAdmin": false + } + ], transaction_id = '' # optional ) diff --git a/docs/examples/embeddings/create-text-embeddings.md b/docs/examples/embeddings/create-text-embeddings.md index 49d3c258..36da57c3 100644 --- a/docs/examples/embeddings/create-text-embeddings.md +++ b/docs/examples/embeddings/create-text-embeddings.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.embeddings import Embeddings from appwrite.models import EmbeddingList -from appwrite.enums import EmbeddingModel +from appwrite.enums.embedding_model import EmbeddingModel client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -12,7 +12,7 @@ client.set_key('') # Your secret API key embeddings = Embeddings(client) result: EmbeddingList = embeddings.create_text_embeddings( - texts = [], + texts = ["Appwrite helps developers build applications.", "Find documents with semantic search."], model = EmbeddingModel.NOMIC_EMBED_TEXT # optional ) diff --git a/docs/examples/functions/create-execution.md b/docs/examples/functions/create-execution.md index c88c00ef..a57c0415 100644 --- a/docs/examples/functions/create-execution.md +++ b/docs/examples/functions/create-execution.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.functions import Functions from appwrite.models import Execution -from appwrite.enums import ExecutionMethod +from appwrite.enums.execution_method import ExecutionMethod client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/functions/create-template-deployment.md b/docs/examples/functions/create-template-deployment.md index 19227be6..cd7511d5 100644 --- a/docs/examples/functions/create-template-deployment.md +++ b/docs/examples/functions/create-template-deployment.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.functions import Functions from appwrite.models import Deployment -from appwrite.enums import TemplateReferenceType +from appwrite.enums.template_reference_type import TemplateReferenceType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/functions/create-vcs-deployment.md b/docs/examples/functions/create-vcs-deployment.md index be644a7c..37a2d604 100644 --- a/docs/examples/functions/create-vcs-deployment.md +++ b/docs/examples/functions/create-vcs-deployment.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.functions import Functions from appwrite.models import Deployment -from appwrite.enums import VCSReferenceType +from appwrite.enums.vcs_reference_type import VCSReferenceType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/functions/create.md b/docs/examples/functions/create.md index 9f61841b..46652c4a 100644 --- a/docs/examples/functions/create.md +++ b/docs/examples/functions/create.md @@ -2,8 +2,8 @@ from appwrite.client import Client from appwrite.services.functions import Functions from appwrite.models import Function -from appwrite.enums import Runtime -from appwrite.enums import ProjectKeyScopes +from appwrite.enums.runtime import Runtime +from appwrite.enums.project_key_scopes import ProjectKeyScopes client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/functions/get-deployment-download.md b/docs/examples/functions/get-deployment-download.md index 49df861b..186211e8 100644 --- a/docs/examples/functions/get-deployment-download.md +++ b/docs/examples/functions/get-deployment-download.md @@ -1,7 +1,7 @@ ```python from appwrite.client import Client from appwrite.services.functions import Functions -from appwrite.enums import DeploymentDownloadType +from appwrite.enums.deployment_download_type import DeploymentDownloadType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/functions/update.md b/docs/examples/functions/update.md index 4e819331..425158bb 100644 --- a/docs/examples/functions/update.md +++ b/docs/examples/functions/update.md @@ -2,8 +2,8 @@ from appwrite.client import Client from appwrite.services.functions import Functions from appwrite.models import Function -from appwrite.enums import Runtime -from appwrite.enums import ProjectKeyScopes +from appwrite.enums.runtime import Runtime +from appwrite.enums.project_key_scopes import ProjectKeyScopes client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -35,7 +35,8 @@ result: Function = functions.update( build_specification = 's-1vcpu-512mb', # optional runtime_specification = 's-1vcpu-512mb', # optional deployment_retention = 0, # optional - interval = 0 # optional + interval = 0, # optional + email_enabled = False # optional ) print(result.model_dump()) diff --git a/docs/examples/graphql/mutation.md b/docs/examples/graphql/mutation.md index 26ed1cbe..a7609b1f 100644 --- a/docs/examples/graphql/mutation.md +++ b/docs/examples/graphql/mutation.md @@ -10,6 +10,8 @@ client.set_key('') # Your secret API key graphql = Graphql(client) result = graphql.mutation( - query = {} + query = { + "query": "mutation { accountUpdateName(name: \"Walter\") { name } }" + } ) ``` diff --git a/docs/examples/graphql/query.md b/docs/examples/graphql/query.md index 94142f99..350c47ba 100644 --- a/docs/examples/graphql/query.md +++ b/docs/examples/graphql/query.md @@ -10,6 +10,8 @@ client.set_key('') # Your secret API key graphql = Graphql(client) result = graphql.query( - query = {} + query = { + "query": "query { localeGet { ip } }" + } ) ``` diff --git a/docs/examples/messaging/create-push.md b/docs/examples/messaging/create-push.md index 0b169447..f4b4ff8c 100644 --- a/docs/examples/messaging/create-push.md +++ b/docs/examples/messaging/create-push.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.messaging import Messaging from appwrite.models import Message -from appwrite.enums import MessagePriority +from appwrite.enums.message_priority import MessagePriority client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/messaging/create-smtp-provider.md b/docs/examples/messaging/create-smtp-provider.md index 9681bc18..98eabeff 100644 --- a/docs/examples/messaging/create-smtp-provider.md +++ b/docs/examples/messaging/create-smtp-provider.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.messaging import Messaging from appwrite.models import Provider -from appwrite.enums import SmtpEncryption +from appwrite.enums.smtp_encryption import SmtpEncryption client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/messaging/create-twilio-provider.md b/docs/examples/messaging/create-twilio-provider.md index 6a20087d..b0e31595 100644 --- a/docs/examples/messaging/create-twilio-provider.md +++ b/docs/examples/messaging/create-twilio-provider.md @@ -13,7 +13,7 @@ messaging = Messaging(client) result: Provider = messaging.create_twilio_provider( provider_id = '', name = '', - from = '+12065550100', # optional + from = '', # optional account_sid = '', # optional auth_token = '', # optional enabled = False # optional diff --git a/docs/examples/messaging/update-push.md b/docs/examples/messaging/update-push.md index cc87614a..0ae36aad 100644 --- a/docs/examples/messaging/update-push.md +++ b/docs/examples/messaging/update-push.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.messaging import Messaging from appwrite.models import Message -from appwrite.enums import MessagePriority +from appwrite.enums.message_priority import MessagePriority client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/messaging/update-smtp-provider.md b/docs/examples/messaging/update-smtp-provider.md index 23294e88..548d72a1 100644 --- a/docs/examples/messaging/update-smtp-provider.md +++ b/docs/examples/messaging/update-smtp-provider.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.messaging import Messaging from appwrite.models import Provider -from appwrite.enums import SmtpEncryption +from appwrite.enums.smtp_encryption import SmtpEncryption client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/mongo/create-restoration.md b/docs/examples/mongo/create-restoration.md index 0ba9b82f..b24a7206 100644 --- a/docs/examples/mongo/create-restoration.md +++ b/docs/examples/mongo/create-restoration.md @@ -15,7 +15,10 @@ result: DedicatedDatabaseRestoration = mongo.create_restoration( type = 'backup', # optional backup_id = '', # optional target_database_id = '', # optional - target_time = '2020-10-15T06:38:00.000+00:00' # optional + target_time = '2020-10-15T06:38:00.000+00:00', # optional + restore_mode = 'in_place', # optional + target_name = '', # optional + auto_promote = False # optional ) print(result.model_dump()) diff --git a/docs/examples/organization/list-keys.md b/docs/examples/mongo/promote-restoration.md similarity index 52% rename from docs/examples/organization/list-keys.md rename to docs/examples/mongo/promote-restoration.md index 41634a0e..826eef23 100644 --- a/docs/examples/organization/list-keys.md +++ b/docs/examples/mongo/promote-restoration.md @@ -1,18 +1,18 @@ ```python from appwrite.client import Client -from appwrite.services.organization import Organization -from appwrite.models import KeyList +from appwrite.services.mongo import Mongo +from appwrite.models import DedicatedDatabaseRestoration client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint client.set_project('') # Your project ID client.set_key('') # Your secret API key -organization = Organization(client) +mongo = Mongo(client) -result: KeyList = organization.list_keys( - queries = [], # optional - total = False # optional +result: DedicatedDatabaseRestoration = mongo.promote_restoration( + database_id = '', + restoration_id = '' ) print(result.model_dump()) diff --git a/docs/examples/mysql/create-restoration.md b/docs/examples/mysql/create-restoration.md index 0c3481f6..f4854228 100644 --- a/docs/examples/mysql/create-restoration.md +++ b/docs/examples/mysql/create-restoration.md @@ -15,7 +15,10 @@ result: DedicatedDatabaseRestoration = mysql.create_restoration( type = 'backup', # optional backup_id = '', # optional target_database_id = '', # optional - target_time = '2020-10-15T06:38:00.000+00:00' # optional + target_time = '2020-10-15T06:38:00.000+00:00', # optional + restore_mode = 'in_place', # optional + target_name = '', # optional + auto_promote = False # optional ) print(result.model_dump()) diff --git a/docs/examples/organization/get-key.md b/docs/examples/mysql/promote-restoration.md similarity index 52% rename from docs/examples/organization/get-key.md rename to docs/examples/mysql/promote-restoration.md index d60f1190..38a54b49 100644 --- a/docs/examples/organization/get-key.md +++ b/docs/examples/mysql/promote-restoration.md @@ -1,17 +1,18 @@ ```python from appwrite.client import Client -from appwrite.services.organization import Organization -from appwrite.models import Key +from appwrite.services.mysql import Mysql +from appwrite.models import DedicatedDatabaseRestoration client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint client.set_project('') # Your project ID client.set_key('') # Your secret API key -organization = Organization(client) +mysql = Mysql(client) -result: Key = organization.get_key( - key_id = '' +result: DedicatedDatabaseRestoration = mysql.promote_restoration( + database_id = '', + restoration_id = '' ) print(result.model_dump()) diff --git a/docs/examples/oauth2/approve.md b/docs/examples/oauth2/approve.md index 12bc9c0d..31bb7317 100644 --- a/docs/examples/oauth2/approve.md +++ b/docs/examples/oauth2/approve.md @@ -5,8 +5,8 @@ from appwrite.models import Oauth2Approve client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_session('') # The user session to authenticate with client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with oauth2 = Oauth2(client) diff --git a/docs/examples/oauth2/authorize-post.md b/docs/examples/oauth2/authorize-post.md index b6dd6449..8cf274b7 100644 --- a/docs/examples/oauth2/authorize-post.md +++ b/docs/examples/oauth2/authorize-post.md @@ -5,8 +5,8 @@ from appwrite.models import Oauth2Authorize client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_session('') # The user session to authenticate with client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with oauth2 = Oauth2(client) @@ -22,7 +22,7 @@ result: Oauth2Authorize = oauth2.authorize_post( prompt = '', # optional max_age = 0, # optional authorization_details = '', # optional - resource = '', # optional + resource = [], # optional audience = '', # optional request_uri = '' # optional ) diff --git a/docs/examples/oauth2/authorize.md b/docs/examples/oauth2/authorize.md index 9d7bb486..32fbf4b2 100644 --- a/docs/examples/oauth2/authorize.md +++ b/docs/examples/oauth2/authorize.md @@ -5,8 +5,8 @@ from appwrite.models import Oauth2Authorize client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_session('') # The user session to authenticate with client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with oauth2 = Oauth2(client) @@ -22,7 +22,7 @@ result: Oauth2Authorize = oauth2.authorize( prompt = '', # optional max_age = 0, # optional authorization_details = '', # optional - resource = '', # optional + resource = [], # optional audience = '', # optional request_uri = '' # optional ) diff --git a/docs/examples/oauth2/create-device-authorization.md b/docs/examples/oauth2/create-device-authorization.md index 0fa3852d..f45ce70c 100644 --- a/docs/examples/oauth2/create-device-authorization.md +++ b/docs/examples/oauth2/create-device-authorization.md @@ -5,8 +5,8 @@ from appwrite.models import Oauth2DeviceAuthorization client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_session('') # The user session to authenticate with client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with oauth2 = Oauth2(client) @@ -14,7 +14,7 @@ result: Oauth2DeviceAuthorization = oauth2.create_device_authorization( client_id = '', # optional scope = '', # optional authorization_details = '', # optional - resource = '', # optional + resource = [], # optional audience = '' # optional ) diff --git a/docs/examples/oauth2/create-grant.md b/docs/examples/oauth2/create-grant.md index 1a87716c..73727320 100644 --- a/docs/examples/oauth2/create-grant.md +++ b/docs/examples/oauth2/create-grant.md @@ -5,8 +5,8 @@ from appwrite.models import Oauth2Grant client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_session('') # The user session to authenticate with client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with oauth2 = Oauth2(client) diff --git a/docs/examples/oauth2/create-par.md b/docs/examples/oauth2/create-par.md index 2018794c..32b72a9d 100644 --- a/docs/examples/oauth2/create-par.md +++ b/docs/examples/oauth2/create-par.md @@ -5,8 +5,8 @@ from appwrite.models import Oauth2PAR client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_session('') # The user session to authenticate with client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with oauth2 = Oauth2(client) @@ -22,7 +22,7 @@ result: Oauth2PAR = oauth2.create_par( prompt = '', # optional max_age = 0, # optional authorization_details = '', # optional - resource = '', # optional + resource = [], # optional audience = '' # optional ) diff --git a/docs/examples/oauth2/create-token.md b/docs/examples/oauth2/create-token.md index 1d52bbc9..6dd3006b 100644 --- a/docs/examples/oauth2/create-token.md +++ b/docs/examples/oauth2/create-token.md @@ -5,8 +5,8 @@ from appwrite.models import Oauth2Token client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_session('') # The user session to authenticate with client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with oauth2 = Oauth2(client) @@ -19,7 +19,7 @@ result: Oauth2Token = oauth2.create_token( client_secret = '', # optional code_verifier = '', # optional redirect_uri = 'https://example.com', # optional - resource = '', # optional + resource = [], # optional audience = '' # optional ) diff --git a/docs/examples/oauth2/get-grant.md b/docs/examples/oauth2/get-grant.md index 51f617f4..77de5ec2 100644 --- a/docs/examples/oauth2/get-grant.md +++ b/docs/examples/oauth2/get-grant.md @@ -5,8 +5,8 @@ from appwrite.models import Oauth2Grant client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_session('') # The user session to authenticate with client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with oauth2 = Oauth2(client) diff --git a/docs/examples/oauth2/list-organizations.md b/docs/examples/oauth2/list-organizations.md index 42ece3a8..5c429e96 100644 --- a/docs/examples/oauth2/list-organizations.md +++ b/docs/examples/oauth2/list-organizations.md @@ -5,8 +5,8 @@ from appwrite.models import Oauth2OrganizationList client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_session('') # The user session to authenticate with client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with oauth2 = Oauth2(client) diff --git a/docs/examples/oauth2/list-projects.md b/docs/examples/oauth2/list-projects.md index 97a58b7b..b6b45f74 100644 --- a/docs/examples/oauth2/list-projects.md +++ b/docs/examples/oauth2/list-projects.md @@ -5,8 +5,8 @@ from appwrite.models import Oauth2ProjectList client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_session('') # The user session to authenticate with client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with oauth2 = Oauth2(client) diff --git a/docs/examples/oauth2/reject.md b/docs/examples/oauth2/reject.md index 63f3335f..1979d517 100644 --- a/docs/examples/oauth2/reject.md +++ b/docs/examples/oauth2/reject.md @@ -5,8 +5,8 @@ from appwrite.models import Oauth2Reject client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_session('') # The user session to authenticate with client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with oauth2 = Oauth2(client) diff --git a/docs/examples/oauth2/revoke.md b/docs/examples/oauth2/revoke.md index 70b94f6d..f351c771 100644 --- a/docs/examples/oauth2/revoke.md +++ b/docs/examples/oauth2/revoke.md @@ -4,8 +4,8 @@ from appwrite.services.oauth2 import Oauth2 client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_session('') # The user session to authenticate with client.set_project('') # Your project ID +client.set_session('') # The user session to authenticate with oauth2 = Oauth2(client) diff --git a/docs/examples/organization/create-key.md b/docs/examples/organization/create-key.md deleted file mode 100644 index 14fee9a7..00000000 --- a/docs/examples/organization/create-key.md +++ /dev/null @@ -1,22 +0,0 @@ -```python -from appwrite.client import Client -from appwrite.services.organization import Organization -from appwrite.models import Key -from appwrite.enums import OrganizationKeyScopes - -client = Client() -client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_project('') # Your project ID -client.set_key('') # Your secret API key - -organization = Organization(client) - -result: Key = organization.create_key( - key_id = '', - name = '', - scopes = [OrganizationKeyScopes.PROJECTS_READ], - expire = '2020-10-15T06:38:00.000+00:00' # optional -) - -print(result.model_dump()) -``` diff --git a/docs/examples/organization/create-project.md b/docs/examples/organization/create-project.md index da78ecff..6d66e4cc 100644 --- a/docs/examples/organization/create-project.md +++ b/docs/examples/organization/create-project.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.organization import Organization from appwrite.models import Project -from appwrite.enums import Region +from appwrite.enums.region import Region client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/organization/delete-key.md b/docs/examples/organization/delete-key.md deleted file mode 100644 index 6e48d845..00000000 --- a/docs/examples/organization/delete-key.md +++ /dev/null @@ -1,15 +0,0 @@ -```python -from appwrite.client import Client -from appwrite.services.organization import Organization - -client = Client() -client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_project('') # Your project ID -client.set_key('') # Your secret API key - -organization = Organization(client) - -result = organization.delete_key( - key_id = '' -) -``` diff --git a/docs/examples/organization/update-key.md b/docs/examples/organization/update-key.md deleted file mode 100644 index 2c32078b..00000000 --- a/docs/examples/organization/update-key.md +++ /dev/null @@ -1,22 +0,0 @@ -```python -from appwrite.client import Client -from appwrite.services.organization import Organization -from appwrite.models import Key -from appwrite.enums import OrganizationKeyScopes - -client = Client() -client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint -client.set_project('') # Your project ID -client.set_key('') # Your secret API key - -organization = Organization(client) - -result: Key = organization.update_key( - key_id = '', - name = '', - scopes = [OrganizationKeyScopes.PROJECTS_READ], - expire = '2020-10-15T06:38:00.000+00:00' # optional -) - -print(result.model_dump()) -``` diff --git a/docs/examples/postgresql/create-restoration.md b/docs/examples/postgresql/create-restoration.md index c4d90b46..b3b5a076 100644 --- a/docs/examples/postgresql/create-restoration.md +++ b/docs/examples/postgresql/create-restoration.md @@ -15,7 +15,10 @@ result: DedicatedDatabaseRestoration = postgresql.create_restoration( type = 'backup', # optional backup_id = '', # optional target_database_id = '', # optional - target_time = '2020-10-15T06:38:00.000+00:00' # optional + target_time = '2020-10-15T06:38:00.000+00:00', # optional + restore_mode = 'in_place', # optional + target_name = '', # optional + auto_promote = False # optional ) print(result.model_dump()) diff --git a/docs/examples/postgresql/promote-restoration.md b/docs/examples/postgresql/promote-restoration.md new file mode 100644 index 00000000..b280f20c --- /dev/null +++ b/docs/examples/postgresql/promote-restoration.md @@ -0,0 +1,19 @@ +```python +from appwrite.client import Client +from appwrite.services.postgresql import Postgresql +from appwrite.models import DedicatedDatabaseRestoration + +client = Client() +client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint +client.set_project('') # Your project ID +client.set_key('') # Your secret API key + +postgresql = Postgresql(client) + +result: DedicatedDatabaseRestoration = postgresql.promote_restoration( + database_id = '', + restoration_id = '' +) + +print(result.model_dump()) +``` diff --git a/docs/examples/project/create-ephemeral-key.md b/docs/examples/project/create-ephemeral-key.md index 17a48da6..c2b202ad 100644 --- a/docs/examples/project/create-ephemeral-key.md +++ b/docs/examples/project/create-ephemeral-key.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import EphemeralKey -from appwrite.enums import ProjectKeyScopes +from appwrite.enums.project_key_scopes import ProjectKeyScopes client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -12,7 +12,7 @@ client.set_key('') # Your secret API key project = Project(client) result: EphemeralKey = project.create_ephemeral_key( - scopes = [ProjectKeyScopes.PROJECT_READ], + scopes = [ProjectKeyScopes.USERS_READ], duration = 600 ) diff --git a/docs/examples/project/create-smtp-test.md b/docs/examples/project/create-smtp-test.md index 3b39979b..e46cb13e 100644 --- a/docs/examples/project/create-smtp-test.md +++ b/docs/examples/project/create-smtp-test.md @@ -10,6 +10,6 @@ client.set_key('') # Your secret API key project = Project(client) result = project.create_smtp_test( - emails = [] + emails = ["recipient@example.com"] ) ``` diff --git a/docs/examples/project/get-email-template.md b/docs/examples/project/get-email-template.md index 8fedaf74..116cc0ae 100644 --- a/docs/examples/project/get-email-template.md +++ b/docs/examples/project/get-email-template.md @@ -2,8 +2,8 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import EmailTemplate -from appwrite.enums import ProjectEmailTemplateId -from appwrite.enums import ProjectEmailTemplateLocale +from appwrite.enums.project_email_template_id import ProjectEmailTemplateId +from appwrite.enums.project_email_template_locale import ProjectEmailTemplateLocale client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/project/get-o-auth-2-provider.md b/docs/examples/project/get-o-auth-2-provider.md index 792ef765..55a01469 100644 --- a/docs/examples/project/get-o-auth-2-provider.md +++ b/docs/examples/project/get-o-auth-2-provider.md @@ -48,7 +48,7 @@ from appwrite.models import OAuth2Microsoft from appwrite.models import OAuth2TikTok from appwrite.models import OAuth2Kakao from typing import Union -from appwrite.enums import ProjectOAuthProviderId +from appwrite.enums.project_o_auth_provider_id import ProjectOAuthProviderId client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/project/get-policy.md b/docs/examples/project/get-policy.md index e5d3e405..3e746d52 100644 --- a/docs/examples/project/get-policy.md +++ b/docs/examples/project/get-policy.md @@ -20,7 +20,7 @@ from appwrite.models import PolicyDenyFreeEmail from appwrite.models import PolicyDenyCorporateEmail from appwrite.models import PolicyPasskey from typing import Union -from appwrite.enums import ProjectPolicyId +from appwrite.enums.project_policy_id import ProjectPolicyId client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/project/update-auth-method.md b/docs/examples/project/update-auth-method.md index d9e4c643..4f562960 100644 --- a/docs/examples/project/update-auth-method.md +++ b/docs/examples/project/update-auth-method.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import Project as ProjectModel -from appwrite.enums import ProjectAuthMethodId +from appwrite.enums.project_auth_method_id import ProjectAuthMethodId client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/project/update-email-template.md b/docs/examples/project/update-email-template.md index d5548fdb..2c679f24 100644 --- a/docs/examples/project/update-email-template.md +++ b/docs/examples/project/update-email-template.md @@ -2,8 +2,8 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import EmailTemplate -from appwrite.enums import ProjectEmailTemplateId -from appwrite.enums import ProjectEmailTemplateLocale +from appwrite.enums.project_email_template_id import ProjectEmailTemplateId +from appwrite.enums.project_email_template_locale import ProjectEmailTemplateLocale client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/project/update-key.md b/docs/examples/project/update-key.md index e1ecc201..a8aa7ccf 100644 --- a/docs/examples/project/update-key.md +++ b/docs/examples/project/update-key.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import Key -from appwrite.enums import ProjectKeyScopes +from appwrite.enums.project_key_scopes import ProjectKeyScopes client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -14,7 +14,7 @@ project = Project(client) result: Key = project.update_key( key_id = '', name = '', - scopes = [ProjectKeyScopes.PROJECT_READ], + scopes = [ProjectKeyScopes.USERS_READ], expire = '2020-10-15T06:38:00.000+00:00' # optional ) diff --git a/docs/examples/project/update-labels.md b/docs/examples/project/update-labels.md index 4fedceb1..ed324cad 100644 --- a/docs/examples/project/update-labels.md +++ b/docs/examples/project/update-labels.md @@ -11,7 +11,7 @@ client.set_key('') # Your secret API key project = Project(client) result: ProjectModel = project.update_labels( - labels = [] + labels = ["production"] ) print(result.model_dump()) diff --git a/docs/examples/project/update-o-auth-2-google.md b/docs/examples/project/update-o-auth-2-google.md index 28fc11e6..5c3e3797 100644 --- a/docs/examples/project/update-o-auth-2-google.md +++ b/docs/examples/project/update-o-auth-2-google.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import OAuth2Google -from appwrite.enums import ProjectOAuth2GooglePrompt +from appwrite.enums.project_o_auth2_google_prompt import ProjectOAuth2GooglePrompt client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/project/update-o-auth-2-kakao.md b/docs/examples/project/update-o-auth-2-kakao.md index b67c6e49..e03afc3f 100644 --- a/docs/examples/project/update-o-auth-2-kakao.md +++ b/docs/examples/project/update-o-auth-2-kakao.md @@ -14,8 +14,8 @@ project = Project(client) result: OAuth2Kakao = project.update_o_auth2_kakao( client_id = '', # optional client_secret = '', # optional - prompt = [ProjectOAuth2KakaoPrompt.NONE], # optional - enabled = False # optional + enabled = False, # optional + prompt = [ProjectOAuth2KakaoPrompt.NONE] # optional ) print(result.model_dump()) diff --git a/docs/examples/project/update-o-auth-2-oidc.md b/docs/examples/project/update-o-auth-2-oidc.md index e2df2e3c..de01460f 100644 --- a/docs/examples/project/update-o-auth-2-oidc.md +++ b/docs/examples/project/update-o-auth-2-oidc.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import OAuth2Oidc -from appwrite.enums import ProjectOAuth2OidcPrompt +from appwrite.enums.project_o_auth2_oidc_prompt import ProjectOAuth2OidcPrompt client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/project/update-protocol.md b/docs/examples/project/update-protocol.md index db26644d..e3d7afc8 100644 --- a/docs/examples/project/update-protocol.md +++ b/docs/examples/project/update-protocol.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import Project as ProjectModel -from appwrite.enums import ProjectProtocolId +from appwrite.enums.project_protocol_id import ProjectProtocolId client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/project/update-service.md b/docs/examples/project/update-service.md index 17c003c0..61b490a6 100644 --- a/docs/examples/project/update-service.md +++ b/docs/examples/project/update-service.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import Project as ProjectModel -from appwrite.enums import ProjectServiceId +from appwrite.enums.project_service_id import ProjectServiceId client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/project/update-smtp.md b/docs/examples/project/update-smtp.md index 772bafea..ae8b2c9f 100644 --- a/docs/examples/project/update-smtp.md +++ b/docs/examples/project/update-smtp.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.project import Project from appwrite.models import Project as ProjectModel -from appwrite.enums import ProjectSMTPSecure +from appwrite.enums.project_smtp_secure import ProjectSMTPSecure client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/proxy/create-invalidation.md b/docs/examples/proxy/create-invalidation.md index 413beb6f..365de03e 100644 --- a/docs/examples/proxy/create-invalidation.md +++ b/docs/examples/proxy/create-invalidation.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.proxy import Proxy from appwrite.models import ProxyInvalidation -from appwrite.enums import InvalidationType +from appwrite.enums.invalidation_type import InvalidationType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/proxy/create-redirect-rule.md b/docs/examples/proxy/create-redirect-rule.md index 7a44bac0..2b4c1934 100644 --- a/docs/examples/proxy/create-redirect-rule.md +++ b/docs/examples/proxy/create-redirect-rule.md @@ -2,8 +2,8 @@ from appwrite.client import Client from appwrite.services.proxy import Proxy from appwrite.models import ProxyRule -from appwrite.enums import StatusCode -from appwrite.enums import ProxyResourceType +from appwrite.enums.status_code import StatusCode +from appwrite.enums.proxy_resource_type import ProxyResourceType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/users/list-logs.md b/docs/examples/proxy/create-smtp-rule.md similarity index 54% rename from docs/examples/users/list-logs.md rename to docs/examples/proxy/create-smtp-rule.md index 34d41e75..c1071fbe 100644 --- a/docs/examples/users/list-logs.md +++ b/docs/examples/proxy/create-smtp-rule.md @@ -1,19 +1,19 @@ ```python from appwrite.client import Client -from appwrite.services.users import Users -from appwrite.models import LogList +from appwrite.services.proxy import Proxy +from appwrite.models import ProxyRule client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint client.set_project('') # Your project ID client.set_key('') # Your secret API key -users = Users(client) +proxy = Proxy(client) -result: LogList = users.list_logs( - user_id = '', - queries = [], # optional - total = False # optional +result: ProxyRule = proxy.create_smtp_rule( + domain = 'example.com', + function_id = '', + branch = '' # optional ) print(result.model_dump()) diff --git a/docs/examples/sites/create-template-deployment.md b/docs/examples/sites/create-template-deployment.md index f65b153b..7be43234 100644 --- a/docs/examples/sites/create-template-deployment.md +++ b/docs/examples/sites/create-template-deployment.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.sites import Sites from appwrite.models import Deployment -from appwrite.enums import TemplateReferenceType +from appwrite.enums.template_reference_type import TemplateReferenceType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/sites/create-vcs-deployment.md b/docs/examples/sites/create-vcs-deployment.md index 1846cefc..3b97fa75 100644 --- a/docs/examples/sites/create-vcs-deployment.md +++ b/docs/examples/sites/create-vcs-deployment.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.sites import Sites from appwrite.models import Deployment -from appwrite.enums import VCSReferenceType +from appwrite.enums.vcs_reference_type import VCSReferenceType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/sites/create.md b/docs/examples/sites/create.md index 8fd41e72..4d8e03bc 100644 --- a/docs/examples/sites/create.md +++ b/docs/examples/sites/create.md @@ -2,10 +2,10 @@ from appwrite.client import Client from appwrite.services.sites import Sites from appwrite.models import Site -from appwrite.enums import Framework -from appwrite.enums import BuildRuntime -from appwrite.enums import Adapter -from appwrite.enums import ProjectKeyScopes +from appwrite.enums.framework import Framework +from appwrite.enums.build_runtime import BuildRuntime +from appwrite.enums.adapter import Adapter +from appwrite.enums.project_key_scopes import ProjectKeyScopes client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/sites/get-deployment-download.md b/docs/examples/sites/get-deployment-download.md index 7d6ae537..0e9ea18a 100644 --- a/docs/examples/sites/get-deployment-download.md +++ b/docs/examples/sites/get-deployment-download.md @@ -1,7 +1,7 @@ ```python from appwrite.client import Client from appwrite.services.sites import Sites -from appwrite.enums import DeploymentDownloadType +from appwrite.enums.deployment_download_type import DeploymentDownloadType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/sites/update.md b/docs/examples/sites/update.md index 0065e89f..59ac85ce 100644 --- a/docs/examples/sites/update.md +++ b/docs/examples/sites/update.md @@ -2,10 +2,10 @@ from appwrite.client import Client from appwrite.services.sites import Sites from appwrite.models import Site -from appwrite.enums import Framework -from appwrite.enums import BuildRuntime -from appwrite.enums import Adapter -from appwrite.enums import ProjectKeyScopes +from appwrite.enums.framework import Framework +from appwrite.enums.build_runtime import BuildRuntime +from appwrite.enums.adapter import Adapter +from appwrite.enums.project_key_scopes import ProjectKeyScopes client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/storage/create-bucket.md b/docs/examples/storage/create-bucket.md index 418f8ecb..76ec2f0e 100644 --- a/docs/examples/storage/create-bucket.md +++ b/docs/examples/storage/create-bucket.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.storage import Storage from appwrite.models import Bucket -from appwrite.enums import Compression +from appwrite.enums.compression import Compression from appwrite.permission import Permission from appwrite.role import Role diff --git a/docs/examples/storage/get-file-preview.md b/docs/examples/storage/get-file-preview.md index 373cb941..f5c8c9db 100644 --- a/docs/examples/storage/get-file-preview.md +++ b/docs/examples/storage/get-file-preview.md @@ -1,8 +1,8 @@ ```python from appwrite.client import Client from appwrite.services.storage import Storage -from appwrite.enums import ImageGravity -from appwrite.enums import ImageFormat +from appwrite.enums.image_gravity import ImageGravity +from appwrite.enums.image_format import ImageFormat client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -16,7 +16,7 @@ result: bytes = storage.get_file_preview( file_id = '', width = 0, # optional height = 0, # optional - gravity = ImageGravity.CENTER, # optional + gravity = ImageGravity.AUTO, # optional quality = -1, # optional border_width = 0, # optional border_color = 'FFFFFF', # optional diff --git a/docs/examples/storage/update-bucket.md b/docs/examples/storage/update-bucket.md index ecb1ada6..c9222517 100644 --- a/docs/examples/storage/update-bucket.md +++ b/docs/examples/storage/update-bucket.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.storage import Storage from appwrite.models import Bucket -from appwrite.enums import Compression +from appwrite.enums.compression import Compression from appwrite.permission import Permission from appwrite.role import Role diff --git a/docs/examples/tablesdb/create-index.md b/docs/examples/tablesdb/create-index.md index 5de707fe..8ecf506d 100644 --- a/docs/examples/tablesdb/create-index.md +++ b/docs/examples/tablesdb/create-index.md @@ -2,8 +2,8 @@ from appwrite.client import Client from appwrite.services.tables_db import TablesDB from appwrite.models import ColumnIndex -from appwrite.enums import TablesDBIndexType -from appwrite.enums import OrderBy +from appwrite.enums.tables_db_index_type import TablesDBIndexType +from appwrite.enums.order_by import OrderBy client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -17,7 +17,7 @@ result: ColumnIndex = tables_db.create_index( table_id = '', key = '', type = TablesDBIndexType.KEY, - columns = [], + columns = ["username"], orders = [OrderBy.ASC], # optional lengths = [] # optional ) diff --git a/docs/examples/tablesdb/create-relationship-column.md b/docs/examples/tablesdb/create-relationship-column.md index ffad0db4..32fc4ba1 100644 --- a/docs/examples/tablesdb/create-relationship-column.md +++ b/docs/examples/tablesdb/create-relationship-column.md @@ -2,8 +2,8 @@ from appwrite.client import Client from appwrite.services.tables_db import TablesDB from appwrite.models import ColumnRelationship -from appwrite.enums import RelationshipType -from appwrite.enums import RelationMutate +from appwrite.enums.relationship_type import RelationshipType +from appwrite.enums.relation_mutate import RelationMutate client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/tablesdb/create-rows.md b/docs/examples/tablesdb/create-rows.md index 9e741fe4..6dc95621 100644 --- a/docs/examples/tablesdb/create-rows.md +++ b/docs/examples/tablesdb/create-rows.md @@ -13,7 +13,16 @@ tables_db = TablesDB(client) result: RowList = tables_db.create_rows( database_id = '', table_id = '', - rows = [], + rows = [ + { + "$id": "example1", + "username": "walter.obrien", + "email": "walter.obrien@example.com", + "fullName": "Walter O'Brien", + "age": 30, + "isAdmin": false + } + ], transaction_id = '' # optional ) diff --git a/docs/examples/tablesdb/delete-rows.md b/docs/examples/tablesdb/delete-rows.md index 2a3a89ca..9ed0672d 100644 --- a/docs/examples/tablesdb/delete-rows.md +++ b/docs/examples/tablesdb/delete-rows.md @@ -13,7 +13,7 @@ tables_db = TablesDB(client) result: RowList = tables_db.delete_rows( database_id = '', table_id = '', - queries = [], # optional + queries = ["{\"method\":\"equal\", \"attribute\":\"$id\", \"values\":[\"\"]}"], # optional transaction_id = '' # optional ) diff --git a/docs/examples/tablesdb/get-column.md b/docs/examples/tablesdb/get-column.md index 6d2b8255..1a4dd142 100644 --- a/docs/examples/tablesdb/get-column.md +++ b/docs/examples/tablesdb/get-column.md @@ -2,6 +2,7 @@ from appwrite.client import Client from appwrite.services.tables_db import TablesDB from appwrite.models import ColumnBoolean +from appwrite.models import ColumnBigint from appwrite.models import ColumnInteger from appwrite.models import ColumnFloat from appwrite.models import ColumnEmail @@ -10,6 +11,13 @@ from appwrite.models import ColumnUrl from appwrite.models import ColumnIp from appwrite.models import ColumnDatetime from appwrite.models import ColumnRelationship +from appwrite.models import ColumnPoint +from appwrite.models import ColumnLine +from appwrite.models import ColumnPolygon +from appwrite.models import ColumnVarchar +from appwrite.models import ColumnText +from appwrite.models import ColumnMediumtext +from appwrite.models import ColumnLongtext from appwrite.models import ColumnString from typing import Union @@ -20,7 +28,7 @@ client.set_key('') # Your secret API key tables_db = TablesDB(client) -result: Union[ColumnBoolean, ColumnInteger, ColumnFloat, ColumnEmail, ColumnEnum, ColumnUrl, ColumnIp, ColumnDatetime, ColumnRelationship, ColumnString] = tables_db.get_column( +result: Union[ColumnBoolean, ColumnBigint, ColumnInteger, ColumnFloat, ColumnEmail, ColumnEnum, ColumnUrl, ColumnIp, ColumnDatetime, ColumnRelationship, ColumnPoint, ColumnLine, ColumnPolygon, ColumnVarchar, ColumnText, ColumnMediumtext, ColumnLongtext, ColumnString] = tables_db.get_column( database_id = '', table_id = '', key = '' diff --git a/docs/examples/tablesdb/update-relationship-column.md b/docs/examples/tablesdb/update-relationship-column.md index 4932a8a9..67fb6063 100644 --- a/docs/examples/tablesdb/update-relationship-column.md +++ b/docs/examples/tablesdb/update-relationship-column.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.tables_db import TablesDB from appwrite.models import ColumnRelationship -from appwrite.enums import RelationMutate +from appwrite.enums.relation_mutate import RelationMutate client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/tablesdb/upsert-rows.md b/docs/examples/tablesdb/upsert-rows.md index 0b6a754e..673b9a2b 100644 --- a/docs/examples/tablesdb/upsert-rows.md +++ b/docs/examples/tablesdb/upsert-rows.md @@ -13,7 +13,16 @@ tables_db = TablesDB(client) result: RowList = tables_db.upsert_rows( database_id = '', table_id = '', - rows = [], + rows = [ + { + "$id": "example1", + "username": "walter.obrien", + "email": "walter.obrien@example.com", + "fullName": "Walter O'Brien", + "age": 30, + "isAdmin": false + } + ], transaction_id = '' # optional ) diff --git a/docs/examples/teams/create-membership.md b/docs/examples/teams/create-membership.md index 5e63bc02..aa247d86 100644 --- a/docs/examples/teams/create-membership.md +++ b/docs/examples/teams/create-membership.md @@ -12,7 +12,7 @@ teams = Teams(client) result: Membership = teams.create_membership( team_id = '', - roles = [], + roles = ["editor"], email = 'email@example.com', # optional user_id = '', # optional phone = '+12065550100', # optional diff --git a/docs/examples/teams/update-membership.md b/docs/examples/teams/update-membership.md index 4425ae58..e6db1a04 100644 --- a/docs/examples/teams/update-membership.md +++ b/docs/examples/teams/update-membership.md @@ -13,7 +13,7 @@ teams = Teams(client) result: Membership = teams.update_membership( team_id = '', membership_id = '', - roles = [] + roles = ["editor"] ) print(result.model_dump()) diff --git a/docs/examples/users/create-sha-user.md b/docs/examples/users/create-sha-user.md index 9d42300a..9b7ef7d3 100644 --- a/docs/examples/users/create-sha-user.md +++ b/docs/examples/users/create-sha-user.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.users import Users from appwrite.models import User -from appwrite.enums import PasswordHash +from appwrite.enums.password_hash import PasswordHash client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/users/create-target.md b/docs/examples/users/create-target.md index fcfd394a..36ce660f 100644 --- a/docs/examples/users/create-target.md +++ b/docs/examples/users/create-target.md @@ -2,7 +2,7 @@ from appwrite.client import Client from appwrite.services.users import Users from appwrite.models import Target -from appwrite.enums import MessagingProviderType +from appwrite.enums.messaging_provider_type import MessagingProviderType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/users/delete-mfa-authenticator.md b/docs/examples/users/delete-mfa-authenticator.md index 67ab6b78..b7cc38c0 100644 --- a/docs/examples/users/delete-mfa-authenticator.md +++ b/docs/examples/users/delete-mfa-authenticator.md @@ -1,7 +1,7 @@ ```python from appwrite.client import Client from appwrite.services.users import Users -from appwrite.enums import AuthenticatorType +from appwrite.enums.authenticator_type import AuthenticatorType client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint diff --git a/docs/examples/users/update-labels.md b/docs/examples/users/update-labels.md index bffba0c1..7d75293f 100644 --- a/docs/examples/users/update-labels.md +++ b/docs/examples/users/update-labels.md @@ -12,7 +12,7 @@ users = Users(client) result: User = users.update_labels( user_id = '', - labels = [] + labels = ["subscriber"] ) print(result.model_dump()) diff --git a/docs/examples/vectorsdb/create-collection.md b/docs/examples/vectorsdb/create-collection.md index 793aa3f5..6dcdeb24 100644 --- a/docs/examples/vectorsdb/create-collection.md +++ b/docs/examples/vectorsdb/create-collection.md @@ -16,7 +16,7 @@ result: VectorsdbCollection = vectors_db.create_collection( database_id = '', collection_id = '', name = '', - dimension = 1, + dimension = 4, permissions = [Permission.read(Role.any())], # optional document_security = False, # optional enabled = False # optional diff --git a/docs/examples/vectorsdb/create-documents.md b/docs/examples/vectorsdb/create-documents.md index b84eea6d..6191c41b 100644 --- a/docs/examples/vectorsdb/create-documents.md +++ b/docs/examples/vectorsdb/create-documents.md @@ -13,7 +13,20 @@ vectors_db = VectorsDB(client) result: DocumentList = vectors_db.create_documents( database_id = '', collection_id = '', - documents = [], + documents = [ + { + "$id": "example1", + "embeddings": [ + 0.12, + -0.55, + 0.88, + 1.02 + ], + "metadata": { + "name": "First document" + } + } + ], transaction_id = '' # optional ) diff --git a/docs/examples/vectorsdb/create-index.md b/docs/examples/vectorsdb/create-index.md index 2f5bf256..71e650a6 100644 --- a/docs/examples/vectorsdb/create-index.md +++ b/docs/examples/vectorsdb/create-index.md @@ -2,8 +2,8 @@ from appwrite.client import Client from appwrite.services.vectors_db import VectorsDB from appwrite.models import Index -from appwrite.enums import VectorsDBIndexType -from appwrite.enums import OrderBy +from appwrite.enums.vectors_db_index_type import VectorsDBIndexType +from appwrite.enums.order_by import OrderBy client = Client() client.set_endpoint('https://.cloud.appwrite.io/v1') # Your API Endpoint @@ -17,7 +17,7 @@ result: Index = vectors_db.create_index( collection_id = '', key = '', type = VectorsDBIndexType.HNSW_EUCLIDEAN, - attributes = [], + attributes = ["embeddings"], orders = [OrderBy.ASC], # optional lengths = [] # optional ) diff --git a/docs/examples/vectorsdb/create-operations.md b/docs/examples/vectorsdb/create-operations.md index e19a8936..f4e1026d 100644 --- a/docs/examples/vectorsdb/create-operations.md +++ b/docs/examples/vectorsdb/create-operations.md @@ -19,7 +19,15 @@ result: Transaction = vectors_db.create_operations( "collectionId": "", "documentId": "", "data": { - "name": "Walter O'Brien" + "embeddings": [ + 0.12, + -0.55, + 0.88, + 1.02 + ], + "metadata": { + "name": "First document" + } } } ] # optional diff --git a/docs/examples/vectorsdb/delete-documents.md b/docs/examples/vectorsdb/delete-documents.md index f1bee6ee..8a36e763 100644 --- a/docs/examples/vectorsdb/delete-documents.md +++ b/docs/examples/vectorsdb/delete-documents.md @@ -13,7 +13,7 @@ vectors_db = VectorsDB(client) result: DocumentList = vectors_db.delete_documents( database_id = '', collection_id = '', - queries = [], # optional + queries = ["{\"method\":\"equal\", \"attribute\":\"$id\", \"values\":[\"\"]}"], # optional transaction_id = '' # optional ) diff --git a/docs/examples/vectorsdb/update-collection.md b/docs/examples/vectorsdb/update-collection.md index 3dcf8903..7093c0b2 100644 --- a/docs/examples/vectorsdb/update-collection.md +++ b/docs/examples/vectorsdb/update-collection.md @@ -16,7 +16,7 @@ result: VectorsdbCollection = vectors_db.update_collection( database_id = '', collection_id = '', name = '', - dimension = 1, # optional + dimension = 4, # optional permissions = [Permission.read(Role.any())], # optional document_security = False, # optional enabled = False # optional diff --git a/docs/examples/vectorsdb/upsert-documents.md b/docs/examples/vectorsdb/upsert-documents.md index 5eb3d2d1..c89ed2f3 100644 --- a/docs/examples/vectorsdb/upsert-documents.md +++ b/docs/examples/vectorsdb/upsert-documents.md @@ -13,7 +13,20 @@ vectors_db = VectorsDB(client) result: DocumentList = vectors_db.upsert_documents( database_id = '', collection_id = '', - documents = [], + documents = [ + { + "$id": "example1", + "embeddings": [ + 0.12, + -0.55, + 0.88, + 1.02 + ], + "metadata": { + "name": "First document" + } + } + ], transaction_id = '' # optional ) diff --git a/docs/examples/webhooks/create.md b/docs/examples/webhooks/create.md index ed957a41..1585ef2b 100644 --- a/docs/examples/webhooks/create.md +++ b/docs/examples/webhooks/create.md @@ -14,7 +14,7 @@ result: Webhook = webhooks.create( webhook_id = '', url = 'https://example.com/webhook', name = '', - events = [], + events = ["users.*.create"], enabled = False, # optional tls = False, # optional auth_username = '', # optional diff --git a/docs/examples/webhooks/update.md b/docs/examples/webhooks/update.md index a6d3ac7b..647e8618 100644 --- a/docs/examples/webhooks/update.md +++ b/docs/examples/webhooks/update.md @@ -14,7 +14,7 @@ result: Webhook = webhooks.update( webhook_id = '', name = '', url = 'https://example.com/webhook', - events = [], + events = ["users.*.create"], enabled = False, # optional tls = False, # optional auth_username = '', # optional diff --git a/pyproject.toml b/pyproject.toml index 805fd42f..f9897243 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "appwrite" -version = "24.4.0" +version = "25.0.0" description = "Appwrite is an open-source self-hosted backend server that abstracts and simplifies complex and repetitive development tasks behind a very simple REST API" readme = "README.md" requires-python = ">=3.9" diff --git a/setup.py b/setup.py index 859b5862..dc433792 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setuptools.setup( name='appwrite', packages=setuptools.find_packages(), - version='24.4.0', + version='25.0.0', license='BSD-3-Clause', description='Appwrite is an open-source self-hosted backend server that abstracts and simplifies complex and repetitive development tasks behind a very simple REST API', long_description=long_description, @@ -18,7 +18,7 @@ maintainer='Appwrite Team', maintainer_email='team@appwrite.io', url='https://appwrite.io/support', - download_url='https://github.com/appwrite/sdk-for-python/archive/24.4.0.tar.gz', + download_url='https://github.com/appwrite/sdk-for-python/archive/25.0.0.tar.gz', install_requires=[ 'requests', 'pydantic>=2,<3', diff --git a/test/services/test_account.py b/test/services/test_account.py index 04c3068a..04fb136f 100644 --- a/test/services/test_account.py +++ b/test/services/test_account.py @@ -261,22 +261,6 @@ def test_delete_identity(self, m): ) self.assertEqual(response, data) - @requests_mock.Mocker() - def test_list_logs(self, m): - data = { - "total": 5.0, - "logs": [], - } - headers = {'Content-Type': 'application/json'} - m.request( - requests_mock.ANY, - requests_mock.ANY, - text=json.dumps(data), - headers=headers, - ) - response = self.account.list_logs() - self.assertEqual(response.to_dict(), data) - @requests_mock.Mocker() def test_update_mfa(self, m): data = { diff --git a/test/services/test_backups.py b/test/services/test_backups.py index a2515204..175b3515 100644 --- a/test/services/test_backups.py +++ b/test/services/test_backups.py @@ -37,9 +37,7 @@ def test_create_archive(self, m): "$createdAt": "2020-10-15T06:38:00.000+00:00", "$updatedAt": "2020-10-15T06:38:00.000+00:00", "policyId": "did8jx6ws45jana098ab7", - "size": 100000.0, "status": "completed", - "startedAt": "2020-10-15T06:38:00.000+00:00", "migrationId": "did8jx6ws45jana098ab7", "services": [], "resources": [], @@ -63,9 +61,7 @@ def test_get_archive(self, m): "$createdAt": "2020-10-15T06:38:00.000+00:00", "$updatedAt": "2020-10-15T06:38:00.000+00:00", "policyId": "did8jx6ws45jana098ab7", - "size": 100000.0, "status": "completed", - "startedAt": "2020-10-15T06:38:00.000+00:00", "migrationId": "did8jx6ws45jana098ab7", "services": [], "resources": [], @@ -138,7 +134,7 @@ def test_create_policy(self, m): '', [], 1, - '', + 'schedule', ) self.assertEqual(response.to_dict(), data) @@ -218,11 +214,10 @@ def test_create_restoration(self, m): "archiveId": "did8jx6ws45jana098ab7", "policyId": "did8jx6ws45jana098ab7", "status": "completed", - "startedAt": "2020-10-15T06:38:00.000+00:00", "migrationId": "did8jx6ws45jana098ab7", "services": [], "resources": [], - "options": "{databases.database[{oldId, newId, newName}]}", + "options": {}, } headers = {'Content-Type': 'application/json'} m.request( @@ -262,11 +257,10 @@ def test_get_restoration(self, m): "archiveId": "did8jx6ws45jana098ab7", "policyId": "did8jx6ws45jana098ab7", "status": "completed", - "startedAt": "2020-10-15T06:38:00.000+00:00", "migrationId": "did8jx6ws45jana098ab7", "services": [], "resources": [], - "options": "{databases.database[{oldId, newId, newName}]}", + "options": {}, } headers = {'Content-Type': 'application/json'} m.request( diff --git a/test/services/test_documents_db.py b/test/services/test_documents_db.py index 05ffaa0d..fb451c82 100644 --- a/test/services/test_documents_db.py +++ b/test/services/test_documents_db.py @@ -58,12 +58,6 @@ def test_list_specifications(self, m): data = { "specifications": [], "total": 9.0, - "pricing": { - "storageOverageRate": 0.125, - "bandwidthOverageRate": 0.08, - "replicaRate": 1, - "pitrRate": 0.2, - }, } headers = {'Content-Type': 'application/json'} m.request( @@ -748,16 +742,12 @@ def test_create_failover(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -767,6 +757,8 @@ def test_create_failover(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -780,7 +772,7 @@ def test_create_failover(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -851,10 +843,6 @@ def test_get_status(self, m): "engine": "postgresql", "version": "17", "uptime": 86400.0, - "connections": { - "current": 12.0, - "max": 100.0, - }, "syncMode": "async", "syncDegraded": True, "syncAcknowledgements": 1.0, diff --git a/test/services/test_functions.py b/test/services/test_functions.py index 16a21555..d515e891 100644 --- a/test/services/test_functions.py +++ b/test/services/test_functions.py @@ -65,6 +65,7 @@ def test_create(self, m): "providerPaths": [], "buildSpecification": "s-1vcpu-512mb", "runtimeSpecification": "s-1vcpu-512mb", + "emailEnabled": True, } headers = {'Content-Type': 'application/json'} m.request( @@ -147,6 +148,7 @@ def test_get(self, m): "providerPaths": [], "buildSpecification": "s-1vcpu-512mb", "runtimeSpecification": "s-1vcpu-512mb", + "emailEnabled": True, } headers = {'Content-Type': 'application/json'} m.request( @@ -195,6 +197,7 @@ def test_update(self, m): "providerPaths": [], "buildSpecification": "s-1vcpu-512mb", "runtimeSpecification": "s-1vcpu-512mb", + "emailEnabled": True, } headers = {'Content-Type': 'application/json'} m.request( @@ -259,6 +262,7 @@ def test_update_function_deployment(self, m): "providerPaths": [], "buildSpecification": "s-1vcpu-512mb", "runtimeSpecification": "s-1vcpu-512mb", + "emailEnabled": True, } headers = {'Content-Type': 'application/json'} m.request( @@ -631,7 +635,7 @@ def test_create_execution(self, m): "responseHeaders": [], "logs": "", "errors": "", - "duration": 0.4, + "duration": 1.23, } headers = {'Content-Type': 'application/json'} m.request( @@ -665,7 +669,7 @@ def test_get_execution(self, m): "responseHeaders": [], "logs": "", "errors": "", - "duration": 0.4, + "duration": 1.23, } headers = {'Content-Type': 'application/json'} m.request( diff --git a/test/services/test_mongo.py b/test/services/test_mongo.py index d66adcb2..75b37bfa 100644 --- a/test/services/test_mongo.py +++ b/test/services/test_mongo.py @@ -38,16 +38,12 @@ def test_create(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -57,6 +53,8 @@ def test_create(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -70,7 +68,7 @@ def test_create(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -99,12 +97,6 @@ def test_list_specifications(self, m): data = { "specifications": [], "total": 9.0, - "pricing": { - "storageOverageRate": 0.125, - "bandwidthOverageRate": 0.08, - "replicaRate": 1, - "pitrRate": 0.2, - }, } headers = {'Content-Type': 'application/json'} m.request( @@ -124,16 +116,12 @@ def test_get(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -143,6 +131,8 @@ def test_get(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -156,7 +146,7 @@ def test_get(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -187,16 +177,12 @@ def test_update(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -206,6 +192,8 @@ def test_update(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -219,7 +207,7 @@ def test_update(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -346,7 +334,7 @@ def test_create_backup_policy(self, m): '', '', '', - '', + 'schedule', 1, ) self.assertEqual(response.to_dict(), data) @@ -517,16 +505,12 @@ def test_create_branch(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -536,6 +520,8 @@ def test_create_branch(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -549,7 +535,7 @@ def test_create_branch(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -580,16 +566,12 @@ def test_delete_branch(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -599,6 +581,8 @@ def test_delete_branch(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -612,7 +596,7 @@ def test_delete_branch(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -668,16 +652,12 @@ def test_create_failover(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -687,6 +667,8 @@ def test_create_failover(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -700,7 +682,7 @@ def test_create_failover(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -731,16 +713,12 @@ def test_update_maintenance(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -750,6 +728,8 @@ def test_update_maintenance(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -763,7 +743,7 @@ def test_update_maintenance(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -796,16 +776,12 @@ def test_create_migration(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -815,6 +791,8 @@ def test_create_migration(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -828,7 +806,7 @@ def test_create_migration(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -934,14 +912,10 @@ def test_create_restoration(self, m): "$id": "5e5ea5c16897e", "$createdAt": "2020-10-15T06:38:00.000+00:00", "databaseId": "5e5ea5c16897e", - "sourceDatabaseId": "5e5ea5c16897e", "projectId": "5e5ea5c16897e", - "backupId": "5e5ea5c16897e", "type": "backup", + "restoreMode": "clone", "status": "completed", - "targetTime": "2020-10-15T06:38:00.000+00:00", - "startedAt": "2020-10-15T06:38:00.000+00:00", - "completedAt": "2020-10-15T06:38:00.000+00:00", "error": "", } headers = {'Content-Type': 'application/json'} @@ -962,14 +936,10 @@ def test_get_restoration(self, m): "$id": "5e5ea5c16897e", "$createdAt": "2020-10-15T06:38:00.000+00:00", "databaseId": "5e5ea5c16897e", - "sourceDatabaseId": "5e5ea5c16897e", "projectId": "5e5ea5c16897e", - "backupId": "5e5ea5c16897e", "type": "backup", + "restoreMode": "clone", "status": "completed", - "targetTime": "2020-10-15T06:38:00.000+00:00", - "startedAt": "2020-10-15T06:38:00.000+00:00", - "completedAt": "2020-10-15T06:38:00.000+00:00", "error": "", } headers = {'Content-Type': 'application/json'} @@ -985,6 +955,31 @@ def test_get_restoration(self, m): ) self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_promote_restoration(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "databaseId": "5e5ea5c16897e", + "projectId": "5e5ea5c16897e", + "type": "backup", + "restoreMode": "clone", + "status": "completed", + "error": "", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.mongo.promote_restoration( + '', + '', + ) + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_get_status(self, m): data = { @@ -993,10 +988,6 @@ def test_get_status(self, m): "engine": "postgresql", "version": "17", "uptime": 86400.0, - "connections": { - "current": 12.0, - "max": 100.0, - }, "syncMode": "async", "syncDegraded": True, "syncAcknowledgements": 1.0, @@ -1024,16 +1015,12 @@ def test_create_upgrade(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -1043,6 +1030,8 @@ def test_create_upgrade(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -1056,7 +1045,7 @@ def test_create_upgrade(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, diff --git a/test/services/test_mysql.py b/test/services/test_mysql.py index 74439293..3ea4f7d3 100644 --- a/test/services/test_mysql.py +++ b/test/services/test_mysql.py @@ -38,16 +38,12 @@ def test_create(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -57,6 +53,8 @@ def test_create(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -70,7 +68,7 @@ def test_create(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -99,12 +97,6 @@ def test_list_specifications(self, m): data = { "specifications": [], "total": 9.0, - "pricing": { - "storageOverageRate": 0.125, - "bandwidthOverageRate": 0.08, - "replicaRate": 1, - "pitrRate": 0.2, - }, } headers = {'Content-Type': 'application/json'} m.request( @@ -124,16 +116,12 @@ def test_get(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -143,6 +131,8 @@ def test_get(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -156,7 +146,7 @@ def test_get(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -187,16 +177,12 @@ def test_update(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -206,6 +192,8 @@ def test_update(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -219,7 +207,7 @@ def test_update(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -346,7 +334,7 @@ def test_create_backup_policy(self, m): '', '', '', - '', + 'schedule', 1, ) self.assertEqual(response.to_dict(), data) @@ -517,16 +505,12 @@ def test_create_branch(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -536,6 +520,8 @@ def test_create_branch(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -549,7 +535,7 @@ def test_create_branch(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -580,16 +566,12 @@ def test_delete_branch(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -599,6 +581,8 @@ def test_delete_branch(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -612,7 +596,7 @@ def test_delete_branch(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -691,16 +675,12 @@ def test_create_failover(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -710,6 +690,8 @@ def test_create_failover(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -723,7 +705,7 @@ def test_create_failover(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -754,16 +736,12 @@ def test_update_maintenance(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -773,6 +751,8 @@ def test_update_maintenance(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -786,7 +766,7 @@ def test_update_maintenance(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -819,16 +799,12 @@ def test_create_migration(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -838,6 +814,8 @@ def test_create_migration(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -851,7 +829,7 @@ def test_create_migration(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -1009,14 +987,10 @@ def test_create_restoration(self, m): "$id": "5e5ea5c16897e", "$createdAt": "2020-10-15T06:38:00.000+00:00", "databaseId": "5e5ea5c16897e", - "sourceDatabaseId": "5e5ea5c16897e", "projectId": "5e5ea5c16897e", - "backupId": "5e5ea5c16897e", "type": "backup", + "restoreMode": "clone", "status": "completed", - "targetTime": "2020-10-15T06:38:00.000+00:00", - "startedAt": "2020-10-15T06:38:00.000+00:00", - "completedAt": "2020-10-15T06:38:00.000+00:00", "error": "", } headers = {'Content-Type': 'application/json'} @@ -1037,14 +1011,10 @@ def test_get_restoration(self, m): "$id": "5e5ea5c16897e", "$createdAt": "2020-10-15T06:38:00.000+00:00", "databaseId": "5e5ea5c16897e", - "sourceDatabaseId": "5e5ea5c16897e", "projectId": "5e5ea5c16897e", - "backupId": "5e5ea5c16897e", "type": "backup", + "restoreMode": "clone", "status": "completed", - "targetTime": "2020-10-15T06:38:00.000+00:00", - "startedAt": "2020-10-15T06:38:00.000+00:00", - "completedAt": "2020-10-15T06:38:00.000+00:00", "error": "", } headers = {'Content-Type': 'application/json'} @@ -1060,6 +1030,31 @@ def test_get_restoration(self, m): ) self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_promote_restoration(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "databaseId": "5e5ea5c16897e", + "projectId": "5e5ea5c16897e", + "type": "backup", + "restoreMode": "clone", + "status": "completed", + "error": "", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.mysql.promote_restoration( + '', + '', + ) + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_get_status(self, m): data = { @@ -1068,10 +1063,6 @@ def test_get_status(self, m): "engine": "postgresql", "version": "17", "uptime": 86400.0, - "connections": { - "current": 12.0, - "max": 100.0, - }, "syncMode": "async", "syncDegraded": True, "syncAcknowledgements": 1.0, @@ -1099,16 +1090,12 @@ def test_create_upgrade(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -1118,6 +1105,8 @@ def test_create_upgrade(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -1131,7 +1120,7 @@ def test_create_upgrade(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, diff --git a/test/services/test_oauth2.py b/test/services/test_oauth2.py index c71e41aa..da2520ee 100644 --- a/test/services/test_oauth2.py +++ b/test/services/test_oauth2.py @@ -68,8 +68,8 @@ def test_create_device_authorization(self, m): data = { "device_code": "5f3c8d2a1b9e4f7a6c8b2d1e9f4a7b3c5d8e1f2a9b4c7d6e3f5a8b1c4d7e2f9a", "user_code": "ABCD-EFGH", - "verification_uri": "https:\/\/cloud.appwrite.io\/console\/oauth2\/device", - "verification_uri_complete": "https:\/\/cloud.appwrite.io\/console\/oauth2\/device?user_code=ABCD-EFGH", + "verification_uri": "https:\/\/appwrite.io\/oauth2\/device", + "verification_uri_complete": "https:\/\/appwrite.io\/oauth2\/device?user_code=ABCD-EFGH", "expires_in": 900.0, "interval": 5.0, } diff --git a/test/services/test_organization.py b/test/services/test_organization.py index e7237111..85ed9358 100644 --- a/test/services/test_organization.py +++ b/test/services/test_organization.py @@ -39,6 +39,7 @@ def test_get(self, m): "screenshotsGenerated": 50.0, "webhooks": 25.0, "wafRules": 2.0, + "environments": 5.0, "projects": 2.0, "platforms": 3.0, "users": 25.0, @@ -63,72 +64,6 @@ def test_get(self, m): "usageLogs": 30.0, "projectInactivityDays": 7.0, "alertLimit": 80.0, - "usage": { - "bandwidth": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "executions": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "realtime": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "realtimeMessages": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "storage": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "users": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "GBHours": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "imageTransformations": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - }, "addons": {}, "budgetCapEnabled": True, "customSmtp": True, @@ -162,13 +97,6 @@ def test_get(self, m): "databaseComputeCredit": 10, }, "billingEmail": "billing@org.example", - "billingStartDate": "2020-10-15T06:38:00.000+00:00", - "billingCurrentInvoiceDate": "2020-10-15T06:38:00.000+00:00", - "billingNextInvoiceDate": "2020-10-15T06:38:00.000+00:00", - "billingTrialDays": 14.0, - "billingAggregationId": "adbc3de4rddfsd", - "billingInvoiceId": "adbc3de4rddfsd", - "paymentMethodId": "adbc3de4rddfsd", "status": "active", "markedForDeletion": True, "platform": "imagine", @@ -209,6 +137,7 @@ def test_update(self, m): "screenshotsGenerated": 50.0, "webhooks": 25.0, "wafRules": 2.0, + "environments": 5.0, "projects": 2.0, "platforms": 3.0, "users": 25.0, @@ -233,72 +162,6 @@ def test_update(self, m): "usageLogs": 30.0, "projectInactivityDays": 7.0, "alertLimit": 80.0, - "usage": { - "bandwidth": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "executions": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "realtime": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "realtimeMessages": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "storage": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "users": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "GBHours": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - "imageTransformations": { - "name": "", - "unit": "GB", - "currency": "USD", - "price": 5, - "value": 25.0, - "invoiceDesc": "", - }, - }, "addons": {}, "budgetCapEnabled": True, "customSmtp": True, @@ -332,13 +195,6 @@ def test_update(self, m): "databaseComputeCredit": 10, }, "billingEmail": "billing@org.example", - "billingStartDate": "2020-10-15T06:38:00.000+00:00", - "billingCurrentInvoiceDate": "2020-10-15T06:38:00.000+00:00", - "billingNextInvoiceDate": "2020-10-15T06:38:00.000+00:00", - "billingTrialDays": 14.0, - "billingAggregationId": "adbc3de4rddfsd", - "billingInvoiceId": "adbc3de4rddfsd", - "paymentMethodId": "adbc3de4rddfsd", "status": "active", "markedForDeletion": True, "platform": "imagine", @@ -475,116 +331,6 @@ def test_delete_installation(self, m): ) self.assertEqual(response, data) - @requests_mock.Mocker() - def test_list_keys(self, m): - data = { - "total": 5.0, - "keys": [], - } - headers = {'Content-Type': 'application/json'} - m.request( - requests_mock.ANY, - requests_mock.ANY, - text=json.dumps(data), - headers=headers, - ) - response = self.organization.list_keys() - self.assertEqual(response.to_dict(), data) - - @requests_mock.Mocker() - def test_create_key(self, m): - data = { - "$id": "5e5ea5c16897e", - "$createdAt": "2020-10-15T06:38:00.000+00:00", - "$updatedAt": "2020-10-15T06:38:00.000+00:00", - "name": "My API Key", - "expire": "2020-10-15T06:38:00.000+00:00", - "scopes": [], - "secret": "919c2d18fb5d4...a2ae413da83346ad2", - "accessedAt": "2020-10-15T06:38:00.000+00:00", - "sdks": [], - } - headers = {'Content-Type': 'application/json'} - m.request( - requests_mock.ANY, - requests_mock.ANY, - text=json.dumps(data), - headers=headers, - ) - response = self.organization.create_key( - '', - '', - [], - ) - self.assertEqual(response.to_dict(), data) - - @requests_mock.Mocker() - def test_get_key(self, m): - data = { - "$id": "5e5ea5c16897e", - "$createdAt": "2020-10-15T06:38:00.000+00:00", - "$updatedAt": "2020-10-15T06:38:00.000+00:00", - "name": "My API Key", - "expire": "2020-10-15T06:38:00.000+00:00", - "scopes": [], - "secret": "919c2d18fb5d4...a2ae413da83346ad2", - "accessedAt": "2020-10-15T06:38:00.000+00:00", - "sdks": [], - } - headers = {'Content-Type': 'application/json'} - m.request( - requests_mock.ANY, - requests_mock.ANY, - text=json.dumps(data), - headers=headers, - ) - response = self.organization.get_key( - '', - ) - self.assertEqual(response.to_dict(), data) - - @requests_mock.Mocker() - def test_update_key(self, m): - data = { - "$id": "5e5ea5c16897e", - "$createdAt": "2020-10-15T06:38:00.000+00:00", - "$updatedAt": "2020-10-15T06:38:00.000+00:00", - "name": "My API Key", - "expire": "2020-10-15T06:38:00.000+00:00", - "scopes": [], - "secret": "919c2d18fb5d4...a2ae413da83346ad2", - "accessedAt": "2020-10-15T06:38:00.000+00:00", - "sdks": [], - } - headers = {'Content-Type': 'application/json'} - m.request( - requests_mock.ANY, - requests_mock.ANY, - text=json.dumps(data), - headers=headers, - ) - response = self.organization.update_key( - '', - '', - [], - ) - self.assertEqual(response.to_dict(), data) - - @requests_mock.Mocker() - def test_delete_key(self, m): - data = '' - headers = {'Content-Type': 'application/json'} - m.request( - requests_mock.ANY, - requests_mock.ANY, - text=json.dumps(data), - headers=headers, - ) - response = self.organization.delete_key( - '', - ) - self.assertEqual(response, data) - @requests_mock.Mocker() def test_list_memberships(self, m): data = { @@ -735,7 +481,6 @@ def test_create_project(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -779,7 +524,6 @@ def test_get_project(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -822,7 +566,6 @@ def test_update_project(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", diff --git a/test/services/test_postgresql.py b/test/services/test_postgresql.py index 4e6beeef..756a1305 100644 --- a/test/services/test_postgresql.py +++ b/test/services/test_postgresql.py @@ -38,16 +38,12 @@ def test_create(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -57,6 +53,8 @@ def test_create(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -70,7 +68,7 @@ def test_create(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -99,12 +97,6 @@ def test_list_specifications(self, m): data = { "specifications": [], "total": 9.0, - "pricing": { - "storageOverageRate": 0.125, - "bandwidthOverageRate": 0.08, - "replicaRate": 1, - "pitrRate": 0.2, - }, } headers = {'Content-Type': 'application/json'} m.request( @@ -124,16 +116,12 @@ def test_get(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -143,6 +131,8 @@ def test_get(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -156,7 +146,7 @@ def test_get(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -187,16 +177,12 @@ def test_update(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -206,6 +192,8 @@ def test_update(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -219,7 +207,7 @@ def test_update(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -346,7 +334,7 @@ def test_create_backup_policy(self, m): '', '', '', - '', + 'schedule', 1, ) self.assertEqual(response.to_dict(), data) @@ -517,16 +505,12 @@ def test_create_branch(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -536,6 +520,8 @@ def test_create_branch(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -549,7 +535,7 @@ def test_create_branch(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -580,16 +566,12 @@ def test_delete_branch(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -599,6 +581,8 @@ def test_delete_branch(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -612,7 +596,7 @@ def test_delete_branch(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -710,16 +694,12 @@ def test_create_extension(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -729,6 +709,8 @@ def test_create_extension(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -742,7 +724,7 @@ def test_create_extension(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -774,16 +756,12 @@ def test_delete_extension(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -793,6 +771,8 @@ def test_delete_extension(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -806,7 +786,7 @@ def test_delete_extension(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -838,16 +818,12 @@ def test_create_failover(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -857,6 +833,8 @@ def test_create_failover(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -870,7 +848,7 @@ def test_create_failover(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -901,16 +879,12 @@ def test_update_maintenance(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -920,6 +894,8 @@ def test_update_maintenance(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -933,7 +909,7 @@ def test_update_maintenance(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -966,16 +942,12 @@ def test_create_migration(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -985,6 +957,8 @@ def test_create_migration(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -998,7 +972,7 @@ def test_create_migration(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -1156,14 +1130,10 @@ def test_create_restoration(self, m): "$id": "5e5ea5c16897e", "$createdAt": "2020-10-15T06:38:00.000+00:00", "databaseId": "5e5ea5c16897e", - "sourceDatabaseId": "5e5ea5c16897e", "projectId": "5e5ea5c16897e", - "backupId": "5e5ea5c16897e", "type": "backup", + "restoreMode": "clone", "status": "completed", - "targetTime": "2020-10-15T06:38:00.000+00:00", - "startedAt": "2020-10-15T06:38:00.000+00:00", - "completedAt": "2020-10-15T06:38:00.000+00:00", "error": "", } headers = {'Content-Type': 'application/json'} @@ -1184,14 +1154,10 @@ def test_get_restoration(self, m): "$id": "5e5ea5c16897e", "$createdAt": "2020-10-15T06:38:00.000+00:00", "databaseId": "5e5ea5c16897e", - "sourceDatabaseId": "5e5ea5c16897e", "projectId": "5e5ea5c16897e", - "backupId": "5e5ea5c16897e", "type": "backup", + "restoreMode": "clone", "status": "completed", - "targetTime": "2020-10-15T06:38:00.000+00:00", - "startedAt": "2020-10-15T06:38:00.000+00:00", - "completedAt": "2020-10-15T06:38:00.000+00:00", "error": "", } headers = {'Content-Type': 'application/json'} @@ -1207,6 +1173,31 @@ def test_get_restoration(self, m): ) self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_promote_restoration(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "databaseId": "5e5ea5c16897e", + "projectId": "5e5ea5c16897e", + "type": "backup", + "restoreMode": "clone", + "status": "completed", + "error": "", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.postgresql.promote_restoration( + '', + '', + ) + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_get_status(self, m): data = { @@ -1215,10 +1206,6 @@ def test_get_status(self, m): "engine": "postgresql", "version": "17", "uptime": 86400.0, - "connections": { - "current": 12.0, - "max": 100.0, - }, "syncMode": "async", "syncDegraded": True, "syncAcknowledgements": 1.0, @@ -1246,16 +1233,12 @@ def test_create_upgrade(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -1265,6 +1248,8 @@ def test_create_upgrade(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -1278,7 +1263,7 @@ def test_create_upgrade(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, diff --git a/test/services/test_project.py b/test/services/test_project.py index 0d5d0b3d..669f0013 100644 --- a/test/services/test_project.py +++ b/test/services/test_project.py @@ -23,7 +23,6 @@ def test_get(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -77,7 +76,6 @@ def test_update_auth_method(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -137,7 +135,6 @@ def test_create_environment(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -181,7 +178,6 @@ def test_get_environment(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -224,7 +220,6 @@ def test_update_environment(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -392,7 +387,6 @@ def test_update_labels(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -544,7 +538,6 @@ def test_update_o_auth2_server(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -606,6 +599,8 @@ def test_update_o_auth2_apple(self, m): "keyId": "P4000000N8", "teamId": "D4000000R6", "p8File": "-----BEGIN PRIVATE KEY-----MIGTAg...jy2Xbna-----END PRIVATE KEY-----", + "nativeEnabled": True, + "nativeClientIds": [], } headers = {'Content-Type': 'application/json'} m.request( @@ -642,6 +637,7 @@ def test_update_o_auth2_auth0(self, m): "enabled": True, "clientId": "OaOkIA000000000000000000005KLSYq", "clientSecret": "zXz0000-00000000000000000000000000000-00000000000000000000PJafnF", + "prompt": [], "endpoint": "example.us.auth0.com", } headers = {'Content-Type': 'application/json'} @@ -788,6 +784,7 @@ def test_update_o_auth2_discord(self, m): "enabled": True, "clientId": "950722000000343754", "clientSecret": "YmPXnM000000000000000000002zFg5D", + "prompt": [], } headers = {'Content-Type': 'application/json'} m.request( @@ -915,6 +912,7 @@ def test_update_o_auth2_git_hub(self, m): "enabled": True, "clientId": "e4d87900000000540733", "clientSecret": "5e07c00000000000000000000000000000198bcc", + "prompt": [], } headers = {'Content-Type': 'application/json'} m.request( @@ -953,6 +951,8 @@ def test_update_o_auth2_google(self, m): "clientId": "120000000095-92ifjb00000000000000000000g7ijfb.apps.googleusercontent.com", "clientSecret": "GOCSPX-2k8gsR0000000000000000VNahJj", "prompt": [], + "nativeEnabled": True, + "nativeClientIds": [], } headers = {'Content-Type': 'application/json'} m.request( @@ -1064,6 +1064,7 @@ def test_update_o_auth2_microsoft(self, m): "enabled": True, "applicationId": "00001111-aaaa-2222-bbbb-3333cccc4444", "applicationSecret": "A1bC2dE3fH4iJ5kL6mN7oP8qR9sT0u", + "prompt": [], "tenant": "common", } headers = {'Content-Type': 'application/json'} @@ -1101,11 +1102,11 @@ def test_update_o_auth2_oidc(self, m): "enabled": True, "clientId": "qibI2x0000000000000000000000000006L2YFoG", "clientSecret": "Ah68ed000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003qpcHV", + "prompt": [], "wellKnownURL": "https:\/\/myoauth.com\/.well-known\/openid-configuration", "authorizationURL": "https:\/\/myoauth.com\/oauth2\/authorize", "tokenURL": "https:\/\/myoauth.com\/oauth2\/token", "userInfoURL": "https:\/\/myoauth.com\/oauth2\/userinfo", - "prompt": [], } headers = {'Content-Type': 'application/json'} m.request( @@ -1124,6 +1125,7 @@ def test_update_o_auth2_okta(self, m): "enabled": True, "clientId": "0oa00000000000000698", "clientSecret": "Kiq0000000000000000000000000000000000000-00000000000H2L5-3SJ-vRV", + "prompt": [], "domain": "trial-6400025.okta.com", "authorizationServerId": "aus000000000000000h7z", } @@ -1216,6 +1218,7 @@ def test_update_o_auth2_salesforce(self, m): "enabled": True, "customerKey": "3MVG9I0000000000000000000000000000000000000000000000000000000000000000000000000C5Aejq", "customerSecret": "3w000000000000e2", + "prompt": [], } headers = {'Content-Type': 'application/json'} m.request( @@ -1450,6 +1453,7 @@ def test_update_o_auth2_zoho(self, m): "enabled": True, "clientId": "1000.83C178000000000000000000RPNX0B", "clientSecret": "fb5cac000000000000000000000000000000a68f6e", + "prompt": [], } headers = {'Content-Type': 'application/json'} m.request( @@ -1486,6 +1490,7 @@ def test_get_o_auth2_provider(self, m): "enabled": True, "clientId": "e4d87900000000540733", "clientSecret": "5e07c00000000000000000000000000000198bcc", + "prompt": [], } headers = {'Content-Type': 'application/json'} m.request( @@ -1524,6 +1529,7 @@ def test_create_android_platform(self, m): "name": "My Web App", "type": "web", "applicationId": "com.company.appname", + "fingerprints": [], } headers = {'Content-Type': 'application/json'} m.request( @@ -1548,6 +1554,7 @@ def test_update_android_platform(self, m): "name": "My Web App", "type": "web", "applicationId": "com.company.appname", + "fingerprints": [], } headers = {'Content-Type': 'application/json'} m.request( @@ -1817,7 +1824,6 @@ def test_update_deny_aliased_email_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -1860,7 +1866,6 @@ def test_update_deny_corporate_email_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -1903,7 +1908,6 @@ def test_update_deny_disposable_email_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -1946,7 +1950,6 @@ def test_update_deny_free_email_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -1989,7 +1992,6 @@ def test_update_membership_privacy_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2030,7 +2032,6 @@ def test_update_mfa_factors_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2071,7 +2072,6 @@ def test_update_passkey_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2114,7 +2114,6 @@ def test_update_password_dictionary_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2157,7 +2156,6 @@ def test_update_password_history_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2200,7 +2198,6 @@ def test_update_password_personal_data_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2243,7 +2240,6 @@ def test_update_password_pwned_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2284,7 +2280,6 @@ def test_update_password_rotation_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2345,7 +2340,6 @@ def test_update_session_alert_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2388,7 +2382,6 @@ def test_update_session_duration_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2431,7 +2424,6 @@ def test_update_session_invalidation_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2474,7 +2466,6 @@ def test_update_session_limit_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2517,7 +2508,6 @@ def test_update_user_limit_policy(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2578,7 +2568,6 @@ def test_update_protocol(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2622,7 +2611,6 @@ def test_update_service(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", @@ -2666,7 +2654,6 @@ def test_update_smtp(self, m): "name": "New Project", "teamId": "1592981250", "region": "fra", - "devKeys": [], "smtpEnabled": True, "smtpSenderName": "John Appwrite", "smtpSenderEmail": "john@appwrite.io", diff --git a/test/services/test_proxy.py b/test/services/test_proxy.py index ad5543f8..c12c5271 100644 --- a/test/services/test_proxy.py +++ b/test/services/test_proxy.py @@ -68,6 +68,7 @@ def test_create_api_rule(self, m): "status": "verified", "logs": "Verification of DNS records failed with DNS resolver 8.8.8.8. Domain stage.myapp.com does not have DNS record.", "renewAt": "datetime", + "protocol": "http", } headers = {'Content-Type': 'application/json'} m.request( @@ -98,6 +99,7 @@ def test_create_function_rule(self, m): "status": "verified", "logs": "Verification of DNS records failed with DNS resolver 8.8.8.8. Domain stage.myapp.com does not have DNS record.", "renewAt": "datetime", + "protocol": "http", } headers = {'Content-Type': 'application/json'} m.request( @@ -129,6 +131,7 @@ def test_create_redirect_rule(self, m): "status": "verified", "logs": "Verification of DNS records failed with DNS resolver 8.8.8.8. Domain stage.myapp.com does not have DNS record.", "renewAt": "datetime", + "protocol": "http", } headers = {'Content-Type': 'application/json'} m.request( @@ -163,6 +166,7 @@ def test_create_site_rule(self, m): "status": "verified", "logs": "Verification of DNS records failed with DNS resolver 8.8.8.8. Domain stage.myapp.com does not have DNS record.", "renewAt": "datetime", + "protocol": "http", } headers = {'Content-Type': 'application/json'} m.request( @@ -177,6 +181,38 @@ def test_create_site_rule(self, m): ) self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_create_smtp_rule(self, m): + data = { + "$id": "5e5ea5c16897e", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "domain": "appwrite.company.com", + "type": "deployment", + "trigger": "manual", + "redirectUrl": "https:\/\/appwrite.io\/docs", + "redirectStatusCode": 301.0, + "deploymentId": "n3u9feiwmf", + "deploymentResourceId": "n3u9feiwmf", + "deploymentVcsProviderBranch": "main", + "status": "verified", + "logs": "Verification of DNS records failed with DNS resolver 8.8.8.8. Domain stage.myapp.com does not have DNS record.", + "renewAt": "datetime", + "protocol": "http", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.proxy.create_smtp_rule( + 'example.com', + '', + ) + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_get_rule(self, m): data = { @@ -194,6 +230,7 @@ def test_get_rule(self, m): "status": "verified", "logs": "Verification of DNS records failed with DNS resolver 8.8.8.8. Domain stage.myapp.com does not have DNS record.", "renewAt": "datetime", + "protocol": "http", } headers = {'Content-Type': 'application/json'} m.request( @@ -239,6 +276,7 @@ def test_update_rule_status(self, m): "status": "verified", "logs": "Verification of DNS records failed with DNS resolver 8.8.8.8. Domain stage.myapp.com does not have DNS record.", "renewAt": "datetime", + "protocol": "http", } headers = {'Content-Type': 'application/json'} m.request( diff --git a/test/services/test_sites.py b/test/services/test_sites.py index f8271b9f..d7b7f32c 100644 --- a/test/services/test_sites.py +++ b/test/services/test_sites.py @@ -644,7 +644,7 @@ def test_get_log(self, m): "responseHeaders": [], "logs": "", "errors": "", - "duration": 0.4, + "duration": 1.23, } headers = {'Content-Type': 'application/json'} m.request( diff --git a/test/services/test_tables_db.py b/test/services/test_tables_db.py index 8c5cfa00..b2e71905 100644 --- a/test/services/test_tables_db.py +++ b/test/services/test_tables_db.py @@ -58,12 +58,6 @@ def test_list_specifications(self, m): data = { "specifications": [], "total": 9.0, - "pricing": { - "storageOverageRate": 0.125, - "bandwidthOverageRate": 0.08, - "replicaRate": 1, - "pitrRate": 0.2, - }, } headers = {'Content-Type': 'application/json'} m.request( @@ -259,16 +253,12 @@ def test_create_failover(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -278,6 +268,8 @@ def test_create_failover(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -291,7 +283,7 @@ def test_create_failover(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -498,10 +490,6 @@ def test_get_status(self, m): "engine": "postgresql", "version": "17", "uptime": 86400.0, - "connections": { - "current": 12.0, - "max": 100.0, - }, "syncMode": "async", "syncDegraded": True, "syncAcknowledgements": 1.0, @@ -1392,6 +1380,37 @@ def test_create_relationship_column(self, m): ) self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() + def test_update_relationship_column(self, m): + data = { + "key": "fullName", + "type": "string", + "status": "available", + "error": "string", + "required": True, + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "relatedTable": "table", + "relationType": "oneToOne|oneToMany|manyToOne|manyToMany", + "twoWay": True, + "twoWayKey": "string", + "onDelete": "restrict|cascade|setNull", + "side": "parent|child", + } + headers = {'Content-Type': 'application/json'} + m.request( + requests_mock.ANY, + requests_mock.ANY, + text=json.dumps(data), + headers=headers, + ) + response = self.tables_db.update_relationship_column( + '', + '', + '', + ) + self.assertEqual(response.to_dict(), data) + @requests_mock.Mocker() def test_create_string_column(self, m): data = { @@ -1654,37 +1673,6 @@ def test_delete_column(self, m): ) self.assertEqual(response, data) - @requests_mock.Mocker() - def test_update_relationship_column(self, m): - data = { - "key": "fullName", - "type": "string", - "status": "available", - "error": "string", - "required": True, - "$createdAt": "2020-10-15T06:38:00.000+00:00", - "$updatedAt": "2020-10-15T06:38:00.000+00:00", - "relatedTable": "table", - "relationType": "oneToOne|oneToMany|manyToOne|manyToMany", - "twoWay": True, - "twoWayKey": "string", - "onDelete": "restrict|cascade|setNull", - "side": "parent|child", - } - headers = {'Content-Type': 'application/json'} - m.request( - requests_mock.ANY, - requests_mock.ANY, - text=json.dumps(data), - headers=headers, - ) - response = self.tables_db.update_relationship_column( - '', - '', - '', - ) - self.assertEqual(response.to_dict(), data) - @requests_mock.Mocker() def test_list_indexes(self, m): data = { diff --git a/test/services/test_users.py b/test/services/test_users.py index d89f4a6d..4dad6e4c 100644 --- a/test/services/test_users.py +++ b/test/services/test_users.py @@ -502,24 +502,6 @@ def test_update_labels(self, m): ) self.assertEqual(response.to_dict(), data) - @requests_mock.Mocker() - def test_list_logs(self, m): - data = { - "total": 5.0, - "logs": [], - } - headers = {'Content-Type': 'application/json'} - m.request( - requests_mock.ANY, - requests_mock.ANY, - text=json.dumps(data), - headers=headers, - ) - response = self.users.list_logs( - '', - ) - self.assertEqual(response.to_dict(), data) - @requests_mock.Mocker() def test_list_memberships(self, m): data = { diff --git a/test/services/test_vectors_db.py b/test/services/test_vectors_db.py index 17cc1f84..5ed5c005 100644 --- a/test/services/test_vectors_db.py +++ b/test/services/test_vectors_db.py @@ -58,12 +58,6 @@ def test_list_specifications(self, m): data = { "specifications": [], "total": 9.0, - "pricing": { - "storageOverageRate": 0.125, - "bandwidthOverageRate": 0.08, - "replicaRate": 1, - "pitrRate": 0.2, - }, } headers = {'Content-Type': 'application/json'} m.request( @@ -717,16 +711,12 @@ def test_create_failover(self, m): "$updatedAt": "2020-10-15T06:38:00.000+00:00", "projectId": "5e5ea5c16897e", "name": "My Production Database", - "api": "postgresql", - "engine": "postgresql", "version": "16", "specification": "s-2vcpu-2gb", "backend": "edge", "hostname": "db-myproject-mydb.fra.appwrite.center", - "connectionPort": 5432.0, "connectionUser": "appwrite_user", "connectionPassword": "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", - "credentialGeneration": 1.0, "connectionString": "postgresql:\/\/user:pass@db-myproject-mydb.fra.appwrite.center:5432\/postgres?sslmode=require", "ssl": True, "status": "ready", @@ -736,6 +726,8 @@ def test_create_failover(self, m): "cpu": 2000.0, "memory": 4096.0, "storage": 100.0, + "storageStatus": "resizing", + "storageTargetGb": 120.0, "storageClass": "ssd", "storageMaxGb": 100.0, "nodePool": "db-pool-4vcpu-8gb", @@ -749,7 +741,7 @@ def test_create_failover(self, m): "pitrRetentionDays": 14.0, "storageAutoscaling": True, "storageAutoscalingThresholdPercent": 85.0, - "storageAutoscalingMaxGb": 500.0, + "storageAutoscalingMaxGb": 30.0, "maintenanceWindowDay": "sun", "maintenanceWindowHourUtc": 3.0, "metricsEnabled": True, @@ -820,10 +812,6 @@ def test_get_status(self, m): "engine": "postgresql", "version": "17", "uptime": 86400.0, - "connections": { - "current": 12.0, - "max": 100.0, - }, "syncMode": "async", "syncDegraded": True, "syncAcknowledgements": 1.0, diff --git a/test/test_query.py b/test/test_query.py index 055fd575..b6a92bbc 100644 --- a/test/test_query.py +++ b/test/test_query.py @@ -1,22 +1,32 @@ +import json import unittest +from urllib.parse import parse_qsl +from urllib.parse import urlsplit +import requests_mock + +from appwrite.client import Client from appwrite.query import Query +def parsed(query): + return json.loads(query) + + class BasicFilterQueryTest: - def __init__(self, description: str, value, expected_values: str): + def __init__(self, description: str, value, expected_values): self.description = description self.value = value self.expected_values = expected_values tests = [ - BasicFilterQueryTest('with a string', 's', '["s"]'), - BasicFilterQueryTest('with an integer', 1, '[1]'), - BasicFilterQueryTest('with a double', 1.2, '[1.2]'), - BasicFilterQueryTest('with a whole number double', 1.0, '[1.0]'), - BasicFilterQueryTest('with a bool', False, '[false]'), - BasicFilterQueryTest('with a list', ['a', 'b', 'c'], '["a","b","c"]'), + BasicFilterQueryTest('with a string', 's', ['s']), + BasicFilterQueryTest('with an integer', 1, [1]), + BasicFilterQueryTest('with a double', 1.2, [1.2]), + BasicFilterQueryTest('with a whole number double', 1.0, [1.0]), + BasicFilterQueryTest('with a bool', False, [False]), + BasicFilterQueryTest('with a list', ['a', 'b', 'c'], ['a', 'b', 'c']), ] @@ -25,89 +35,343 @@ class TestQueryMethods(unittest.TestCase): def test_equal(self): for t in tests: self.assertEqual( - Query.equal('attr', t.value), - f'{{"method":"equal","attribute":"attr","values":{t.expected_values}}}', + parsed(Query.equal('attr', t.value)), + {'method': 'equal', 'attribute': 'attr', 'values': t.expected_values}, t.description, ) def test_not_equal(self): for t in tests: self.assertEqual( - Query.not_equal('attr', t.value), - f'{{"method":"notEqual","attribute":"attr","values":{t.expected_values}}}', + parsed(Query.not_equal('attr', t.value)), + {'method': 'notEqual', 'attribute': 'attr', 'values': t.expected_values}, t.description, ) def test_less_than(self): for t in tests: self.assertEqual( - Query.less_than('attr', t.value), - f'{{"method":"lessThan","attribute":"attr","values":{t.expected_values}}}', + parsed(Query.less_than('attr', t.value)), + {'method': 'lessThan', 'attribute': 'attr', 'values': t.expected_values}, t.description, ) def test_less_than_equal(self): for t in tests: self.assertEqual( - Query.less_than_equal('attr', t.value), - f'{{"method":"lessThanEqual","attribute":"attr","values":{t.expected_values}}}', + parsed(Query.less_than_equal('attr', t.value)), + {'method': 'lessThanEqual', 'attribute': 'attr', 'values': t.expected_values}, t.description, ) def test_greater_than(self): for t in tests: self.assertEqual( - Query.greater_than('attr', t.value), - f'{{"method":"greaterThan","attribute":"attr","values":{t.expected_values}}}', + parsed(Query.greater_than('attr', t.value)), + {'method': 'greaterThan', 'attribute': 'attr', 'values': t.expected_values}, t.description, ) def test_greater_than_equal(self): for t in tests: self.assertEqual( - Query.greater_than_equal('attr', t.value), - f'{{"method":"greaterThanEqual","attribute":"attr","values":{t.expected_values}}}', + parsed(Query.greater_than_equal('attr', t.value)), + {'method': 'greaterThanEqual', 'attribute': 'attr', 'values': t.expected_values}, t.description, ) def test_search(self): self.assertEqual( - Query.search('attr', 'keyword1 keyword2'), - '{"method":"search","attribute":"attr","values":["keyword1 keyword2"]}', + parsed(Query.search('attr', 'keyword1 keyword2')), + {'method': 'search', 'attribute': 'attr', 'values': ['keyword1 keyword2']}, ) def test_is_null(self): - self.assertEqual(Query.is_null('attr'), '{"method":"isNull","attribute":"attr"}') + self.assertEqual(parsed(Query.is_null('attr')), {'method': 'isNull', 'attribute': 'attr'}) def test_is_not_null(self): - self.assertEqual(Query.is_not_null('attr'), '{"method":"isNotNull","attribute":"attr"}') + self.assertEqual(parsed(Query.is_not_null('attr')), {'method': 'isNotNull', 'attribute': 'attr'}) def test_between_with_integers(self): - self.assertEqual(Query.between('attr', 1, 2), '{"method":"between","attribute":"attr","values":[1,2]}') + self.assertEqual( + parsed(Query.between('attr', 1, 2)), {'method': 'between', 'attribute': 'attr', 'values': [1, 2]} + ) def test_between_with_doubles(self): - self.assertEqual(Query.between('attr', 1.0, 2.0), '{"method":"between","attribute":"attr","values":[1.0,2.0]}') + self.assertEqual( + parsed(Query.between('attr', 1.0, 2.0)), {'method': 'between', 'attribute': 'attr', 'values': [1.0, 2.0]} + ) def test_between_with_strings(self): - self.assertEqual(Query.between('attr', 'a', 'z'), '{"method":"between","attribute":"attr","values":["a","z"]}') + self.assertEqual( + parsed(Query.between('attr', 'a', 'z')), {'method': 'between', 'attribute': 'attr', 'values': ['a', 'z']} + ) def test_select(self): - self.assertEqual(Query.select(['attr1', 'attr2']), '{"method":"select","values":["attr1","attr2"]}') + self.assertEqual(parsed(Query.select(['attr1', 'attr2'])), {'method': 'select', 'values': ['attr1', 'attr2']}) def test_order_asc(self): - self.assertEqual(Query.order_asc('attr'), '{"method":"orderAsc","attribute":"attr"}') + self.assertEqual(parsed(Query.order_asc('attr')), {'method': 'orderAsc', 'attribute': 'attr'}) def test_order_desc(self): - self.assertEqual(Query.order_desc('attr'), '{"method":"orderDesc","attribute":"attr"}') + self.assertEqual(parsed(Query.order_desc('attr')), {'method': 'orderDesc', 'attribute': 'attr'}) def test_cursor_before(self): - self.assertEqual(Query.cursor_before('custom'), '{"method":"cursorBefore","values":["custom"]}') + self.assertEqual(parsed(Query.cursor_before('custom')), {'method': 'cursorBefore', 'values': ['custom']}) def test_cursor_after(self): - self.assertEqual(Query.cursor_after('custom'), '{"method":"cursorAfter","values":["custom"]}') + self.assertEqual(parsed(Query.cursor_after('custom')), {'method': 'cursorAfter', 'values': ['custom']}) def test_limit(self): - self.assertEqual(Query.limit(1), '{"method":"limit","values":[1]}') + self.assertEqual(parsed(Query.limit(1)), {'method': 'limit', 'values': [1]}) def test_offset(self): - self.assertEqual(Query.offset(1), '{"method":"offset","values":[1]}') + self.assertEqual(parsed(Query.offset(1)), {'method': 'offset', 'values': [1]}) + + def test_count(self): + self.assertEqual(parsed(Query.count('*', 'total')), {'method': 'count', 'attribute': '*', 'values': ['total']}) + + def test_count_distinct(self): + self.assertEqual( + parsed(Query.count_distinct('year', 'uniqueYears')), + {'method': 'countDistinct', 'attribute': 'year', 'values': ['uniqueYears']}, + ) + + def test_sum(self): + self.assertEqual( + parsed(Query.sum('price', 'total')), {'method': 'sum', 'attribute': 'price', 'values': ['total']} + ) + + def test_avg(self): + self.assertEqual( + parsed(Query.avg('price', 'avgPrice')), {'method': 'avg', 'attribute': 'price', 'values': ['avgPrice']} + ) + + def test_min(self): + self.assertEqual( + parsed(Query.min('price', 'lowest')), {'method': 'min', 'attribute': 'price', 'values': ['lowest']} + ) + + def test_max(self): + self.assertEqual( + parsed(Query.max('price', 'highest')), {'method': 'max', 'attribute': 'price', 'values': ['highest']} + ) + + def test_stddev(self): + self.assertEqual( + parsed(Query.stddev('price', 'sd')), {'method': 'stddev', 'attribute': 'price', 'values': ['sd']} + ) + + def test_stddev_pop(self): + self.assertEqual( + parsed(Query.stddev_pop('price', 'sdp')), {'method': 'stddevPop', 'attribute': 'price', 'values': ['sdp']} + ) + + def test_stddev_samp(self): + self.assertEqual( + parsed(Query.stddev_samp('price', 'sds')), {'method': 'stddevSamp', 'attribute': 'price', 'values': ['sds']} + ) + + def test_variance(self): + self.assertEqual( + parsed(Query.variance('price', 'var')), {'method': 'variance', 'attribute': 'price', 'values': ['var']} + ) + + def test_var_pop(self): + self.assertEqual( + parsed(Query.var_pop('price', 'vp')), {'method': 'varPop', 'attribute': 'price', 'values': ['vp']} + ) + + def test_var_samp(self): + self.assertEqual( + parsed(Query.var_samp('price', 'vs')), {'method': 'varSamp', 'attribute': 'price', 'values': ['vs']} + ) + + def test_bit_and(self): + self.assertEqual( + parsed(Query.bit_and('flags', 'band')), {'method': 'bitAnd', 'attribute': 'flags', 'values': ['band']} + ) + + def test_bit_or(self): + self.assertEqual( + parsed(Query.bit_or('flags', 'bor')), {'method': 'bitOr', 'attribute': 'flags', 'values': ['bor']} + ) + + def test_bit_xor(self): + self.assertEqual( + parsed(Query.bit_xor('flags', 'bxor')), {'method': 'bitXor', 'attribute': 'flags', 'values': ['bxor']} + ) + + def test_having(self): + query = json.loads(Query.having([Query.greater_than('total', 1)])) + self.assertEqual(query['method'], 'having') + self.assertEqual(query['values'][0]['method'], 'greaterThan') + + def test_join(self): + self.assertEqual( + parsed(Query.join('orders', '$id', 'customerId')), + {'method': 'join', 'attribute': 'orders', 'values': ['$id', '=', 'customerId']}, + ) + + def test_on(self): + self.assertEqual(parsed(Query.on('$id', 'customerId')), {'method': 'on', 'values': ['$id', '=', 'customerId']}) + + def test_nested_left_join(self): + query = json.loads( + Query.left_join( + 'orders', + 'ord', + [ + Query.on('$id', 'customerId'), + Query.equal('ord.status', 'paid'), + ], + ) + ) + self.assertEqual(query['method'], 'leftJoin') + self.assertEqual(query['attribute'], 'orders') + self.assertEqual(query['values'][0], 'ord') + self.assertEqual(query['values'][1]['method'], 'on') + self.assertEqual(query['values'][2]['method'], 'equal') + + def test_group_by(self): + self.assertEqual(parsed(Query.group_by(['status'])), {'method': 'groupBy', 'values': ['status']}) + + def test_distinct(self): + self.assertEqual(parsed(Query.distinct()), {'method': 'distinct'}) + + def test_covers(self): + self.assertEqual( + parsed(Query.covers('location', [1, 2])), {'method': 'covers', 'attribute': 'location', 'values': [[1, 2]]} + ) + + def test_left_join(self): + self.assertEqual( + parsed(Query.left_join('orders', '$id', 'customerId', '=', 'ord')), + {'method': 'leftJoin', 'attribute': 'orders', 'values': ['$id', '=', 'customerId', 'ord']}, + ) + + def test_right_join(self): + self.assertEqual( + parsed(Query.right_join('orders', '$id', 'customerId')), + {'method': 'rightJoin', 'attribute': 'orders', 'values': ['$id', '=', 'customerId']}, + ) + + def test_full_outer_join(self): + self.assertEqual( + parsed(Query.full_outer_join('orders', '$id', 'customerId')), + {'method': 'fullOuterJoin', 'attribute': 'orders', 'values': ['$id', '=', 'customerId']}, + ) + + def test_cross_join(self): + self.assertEqual( + parsed(Query.cross_join('orders', 'ord')), {'method': 'crossJoin', 'attribute': 'orders', 'values': ['ord']} + ) + + def test_not_covers(self): + self.assertEqual( + parsed(Query.not_covers('location', [1, 2])), + {'method': 'notCovers', 'attribute': 'location', 'values': [[1, 2]]}, + ) + + def test_spatial_equals(self): + self.assertEqual( + parsed(Query.spatial_equals('location', [1, 2])), + {'method': 'spatialEquals', 'attribute': 'location', 'values': [[1, 2]]}, + ) + + def test_not_spatial_equals(self): + self.assertEqual( + parsed(Query.not_spatial_equals('location', [1, 2])), + {'method': 'notSpatialEquals', 'attribute': 'location', 'values': [[1, 2]]}, + ) + + def test_page(self): + queries = [parsed(query) for query in Query.page(2, 10)] + self.assertEqual( + queries, + [ + {'method': 'limit', 'values': [10]}, + {'method': 'offset', 'values': [10]}, + ], + ) + + def test_builder_build(self): + expected = [ + Query.equal('status', 'published'), + Query.left_join('orders', '$id', 'customerId', '=', 'ord'), + Query.count('*', 'total'), + Query.group_by(['status']), + Query.limit(25), + ] + built = ( + Query.builder() + .equal('status', 'published') + .left_join('orders', '$id', 'customerId', '=', 'ord') + .count('*', 'total') + .group_by(['status']) + .limit(25) + .build() + ) + self.assertEqual(expected, built) + + def test_flatten_spreads_wrapped_builder(self): + self.assertEqual([Query.limit(1)], Query._flatten([Query.builder().limit(1)])) + + def test_flatten_keeps_nested_numeric_arrays(self): + geometry = [[1, 2], [3, 4]] + self.assertEqual(geometry, Query._flatten(geometry)) + + def test_flatten_keeps_query_string_list(self): + self.assertEqual([Query.limit(1)], Query._flatten([Query.limit(1)])) + + def test_flatten_keeps_nested_string_arrays(self): + nested = [['a', 'b']] + self.assertEqual([['a', 'b']], Query._flatten(nested)) + + def test_flatten_builder_param_becomes_query_strings(self): + builder = Query.builder().equal('status', 'active').limit(1) + self.assertEqual([Query.equal('status', 'active'), Query.limit(1)], Query._flatten(builder)) + + def test_flatten_splices_builders_beside_nested_string_arrays(self): + builder = Query.builder().limit(1).offset(2) + self.assertEqual( + [Query.limit(1), Query.offset(2), ['a', 'b']], + Query._flatten([builder, ['a', 'b']]), + ) + + @requests_mock.Mocker() + def test_client_sends_flattened_params(self, m): + m.register_uri( + requests_mock.ANY, + requests_mock.ANY, + json={}, + headers={'Content-Type': 'application/json'}, + ) + client = Client().set_endpoint('https://example.com/v1') + queries = [Query.limit(1), Query.offset(2)] + + def params(): + return {'queries': Query.builder().limit(1).offset(2), 'tags': [['a', 'b']]} + + client.call('post', '/items', {'content-type': 'application/json'}, params()) + client.call('get', '/items', {'content-type': 'application/json'}, params()) + client.call('post', '/items', {'content-type': 'multipart/form-data'}, params()) + + json_request, get_request, multipart_request = m.request_history + self.assertEqual( + {'queries': queries, 'tags': [['a', 'b']]}, + json.loads(json_request.body), + ) + self.assertEqual( + [ + ('queries[0]', queries[0]), + ('queries[1]', queries[1]), + ('tags[0][0]', 'a'), + ('tags[0][1]', 'b'), + ], + parse_qsl(urlsplit(get_request.url).query), + ) + multipart_body = multipart_request.body.decode() + self.assertIn('name="tags[0][0]"\r\n\r\na\r\n', multipart_body) + self.assertIn('name="tags[0][1]"\r\n\r\nb\r\n', multipart_body) + self.assertIn(f'name="queries[1]"\r\n\r\n{queries[1]}\r\n', multipart_body) diff --git a/test/test_topic.py b/test/test_topic.py new file mode 100644 index 00000000..791e549f --- /dev/null +++ b/test/test_topic.py @@ -0,0 +1,33 @@ +import unittest + +from appwrite.topic import Topic + + +class TestTopicMethods(unittest.TestCase): + + def test_path(self): + self.assertEqual(str(Topic.path(['user'])), 'user') + self.assertEqual(str(Topic.path(['user', 'notification'])), 'user/notification') + self.assertEqual(str(Topic.path(['user']).path(['notification'])), 'user/notification') + self.assertEqual(str(Topic.path(['org', '42']).path(['logs'])), 'org/42/logs') + + def test_errors(self): + cases = [ + ('user', TypeError), + ([], ValueError), + (['user', 42], TypeError), + (['user', None], TypeError), + (['user', ''], ValueError), + (['user/123'], ValueError), + (['user', '+'], ValueError), + (['user', 'a+b'], ValueError), + (['user', '#'], ValueError), + (['user', 'a#b'], ValueError), + (['user', 'a\x00b'], ValueError), + ] + for levels, error in cases: + with self.subTest(levels=levels): + with self.assertRaises(error): + Topic.path(levels) + with self.assertRaises(error): + Topic.path(['user']).path(levels)