Skip to content
22 changes: 15 additions & 7 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,28 @@ name: Publish to PyPI
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: 'Release tag to publish, e.g. 1.2.3'
required: true

jobs:
publish:
name: Release build and publish
runs-on: ubuntu-latest
permissions:
# Mints the short-lived OIDC token PyPI exchanges for an upload token, so
# no long-lived API token has to be stored on the repository.
id-token: write
steps:
- name: Check out code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# A release build must come from the tag, never from a branch that may
# have moved on. On a release event github.ref is already the tag; on a
# manual retry the tag has to be named explicitly.
ref: ${{ inputs.tag || github.ref }}
Comment thread
greptile-apps[bot] marked this conversation as resolved.

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
Expand All @@ -22,10 +36,4 @@ jobs:
python setup.py sdist bdist_wheel

- name: Publish package
run: |
python -m pip install twine
python -m twine upload -r pypi dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
TWINE_NON_INTERACTIVE: true
uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Change Log

## 23.0.0

* Breaking: removed `account.createJWT`; use `users.createJWT` instead. A leaked JWT could mint further JWTs, letting a credential outlive its own expiry — a session cannot duplicate itself to live forever either
* Breaking: removed `project.createKey`. A leaked key could mint further hidden keys, making a compromise far harder to contain and revoke
* Breaking: `activities.listEvents` `queries` now takes an array instead of a string
* Added: `embeddings` service with `createTextEmbeddings`, plus the `EmbeddingModel` enum
* Added: TablesDB migration methods `listMigrations`, `createMigration`, `getMigration`, `deleteMigration`, `cutoverMigration`, and `listOperations`
* Added: `proxy.createInvalidation` for purging cached edge responses, plus the `InvalidationType` enum
* Added: `apps.deleteInstallation`
* Added: `users.getMFAChallenge` and the `MfaChallengeSecret` model
* Added: `project.updateMFAFactorsPolicy` and the `PolicyMfaFactors` model
* Added: `client.setOrganization` for organization-scoped requests
* Added: `folder` parameter to `storage.createFile`
* Added: `syncMode` parameter to `tablesDB.create` and `tablesDB.update`, and `specification` to `tablesDB.update`
* Added: `installationScopes` parameter to `project.updateOAuth2Server`
* Added: `custom` authentication factor, `node-26` runtime, `mfa-factors` project policy, and the `embeddings.write` and `proxy.invalidations.write` key scopes
* Updated: response format to `1.9.6`

## 22.2.0

* Added: `apps` installation and key management methods (`list_installations`, `get_installation`, `create_installation_token`, `list_installation_scopes`, `list_keys`, `create_key`, `get_key`, `delete_key`)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# 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-1.9.5-blue.svg?style=flat-square)
![Version](https://img.shields.io/badge/api%20version-1.9.6-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)
Expand Down
13 changes: 10 additions & 3 deletions appwrite/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ def __init__(self):
self._endpoint = 'https://cloud.appwrite.io/v1'
self._global_headers = {
'content-type': '',
'user-agent' : f'AppwritePythonSDK/22.2.0 ({platform.uname().system}; {platform.uname().version}; {platform.uname().machine})',
'user-agent' : f'AppwritePythonSDK/23.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': '22.2.0',
'X-Appwrite-Response-Format' : '1.9.5',
'x-sdk-version': '23.0.0',
'X-Appwrite-Response-Format' : '1.9.6',
}
self._config = {}

Expand Down Expand Up @@ -60,6 +60,13 @@ def set_key(self, value):
self._config['key'] = value
return self

def set_organization(self, value):
"""Your organization ID"""

self._global_headers['x-appwrite-organization'] = value
self._config['organization'] = value
return self

def set_jwt(self, value):
"""Your secret JSON Web Token"""

Expand Down
8 changes: 8 additions & 0 deletions appwrite/encoders/value_class_encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from ..enums.relation_mutate import RelationMutate
from ..enums.databases_index_type import DatabasesIndexType
from ..enums.order_by import OrderBy
from ..enums.embedding_model import EmbeddingModel
from ..enums.runtime import Runtime
from ..enums.project_key_scopes import ProjectKeyScopes
from ..enums.template_reference_type import TemplateReferenceType
Expand All @@ -35,6 +36,7 @@
from ..enums.project_smtp_secure import ProjectSMTPSecure
from ..enums.project_email_template_id import ProjectEmailTemplateId
from ..enums.project_email_template_locale import ProjectEmailTemplateLocale
from ..enums.invalidation_type import InvalidationType
from ..enums.status_code import StatusCode
from ..enums.proxy_resource_type import ProxyResourceType
from ..enums.framework import Framework
Expand Down Expand Up @@ -111,6 +113,9 @@ def default(self, o):
if isinstance(o, OrderBy):
return o.value

if isinstance(o, EmbeddingModel):
return o.value

if isinstance(o, Runtime):
return o.value

Expand Down Expand Up @@ -171,6 +176,9 @@ def default(self, o):
if isinstance(o, ProjectEmailTemplateLocale):
return o.value

if isinstance(o, InvalidationType):
return o.value

if isinstance(o, StatusCode):
return o.value

Expand Down
1 change: 1 addition & 0 deletions appwrite/enums/authentication_factor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ class AuthenticationFactor(Enum):
PHONE = "phone"
TOTP = "totp"
RECOVERYCODE = "recoverycode"
CUSTOM = "custom"
1 change: 1 addition & 0 deletions appwrite/enums/build_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class BuildRuntime(Enum):
NODE_23 = "node-23"
NODE_24 = "node-24"
NODE_25 = "node-25"
NODE_26 = "node-26"
PHP_8_0 = "php-8.0"
PHP_8_1 = "php-8.1"
PHP_8_2 = "php-8.2"
Expand Down
7 changes: 7 additions & 0 deletions appwrite/enums/embedding_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from enum import Enum

class EmbeddingModel(Enum):
NOMIC_EMBED_TEXT = "nomic-embed-text"
EMBEDDING_GEMMA = "embedding-gemma"
ALL_MINILM = "all-minilm"
BGE_SMALL = "bge-small"
6 changes: 6 additions & 0 deletions appwrite/enums/invalidation_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from enum import Enum

class InvalidationType(Enum):
TAG = "tag"
PATH = "path"
ALL = "all"
2 changes: 2 additions & 0 deletions appwrite/enums/project_key_scopes.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class ProjectKeyScopes(Enum):
INDEXES_WRITE = "indexes.write"
ROWS_READ = "rows.read"
ROWS_WRITE = "rows.write"
EMBEDDINGS_WRITE = "embeddings.write"
COLLECTIONS_READ = "collections.read"
COLLECTIONS_WRITE = "collections.write"
ATTRIBUTES_READ = "attributes.read"
Expand Down Expand Up @@ -99,6 +100,7 @@ class ProjectKeyScopes(Enum):
WAFRULES_READ = "wafRules.read"
WAFRULES_WRITE = "wafRules.write"
EVENTS_READ = "events.read"
PROXY_INVALIDATIONS_WRITE = "proxy.invalidations.write"
APPS_READ = "apps.read"
APPS_WRITE = "apps.write"
OAUTH2_READ = "oauth2.read"
Expand Down
1 change: 1 addition & 0 deletions appwrite/enums/project_policy_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class ProjectPolicyId(Enum):
SESSION_LIMIT = "session-limit"
USER_LIMIT = "user-limit"
MEMBERSHIP_PRIVACY = "membership-privacy"
MFA_FACTORS = "mfa-factors"
DENY_ALIASED_EMAIL = "deny-aliased-email"
DENY_DISPOSABLE_EMAIL = "deny-disposable-email"
DENY_FREE_EMAIL = "deny-free-email"
Expand Down
1 change: 1 addition & 0 deletions appwrite/enums/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class Runtime(Enum):
NODE_23 = "node-23"
NODE_24 = "node-24"
NODE_25 = "node-25"
NODE_26 = "node-26"
PHP_8_0 = "php-8.0"
PHP_8_1 = "php-8.1"
PHP_8_2 = "php-8.2"
Expand Down
18 changes: 18 additions & 0 deletions appwrite/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,11 @@
from .target_list import TargetList
from .transaction_list import TransactionList
from .specification_list import SpecificationList
from .embedding_list import EmbeddingList
from .insight_list import InsightList
from .report_list import ReportList
from .database import Database
from .embedding import Embedding
from .collection import Collection
from .attribute_list import AttributeList
from .attribute_string import AttributeString
Expand Down Expand Up @@ -180,6 +182,7 @@
from .policy_session_limit import PolicySessionLimit
from .policy_user_limit import PolicyUserLimit
from .policy_membership_privacy import PolicyMembershipPrivacy
from .policy_mfa_factors import PolicyMfaFactors
from .platform_web import PlatformWeb
from .platform_apple import PlatformApple
from .platform_android import PlatformAndroid
Expand All @@ -197,6 +200,7 @@
from .proxy_rule import ProxyRule
from .email_template import EmailTemplate
from .mfa_challenge import MfaChallenge
from .mfa_challenge_secret import MfaChallengeSecret
from .mfa_recovery_codes import MfaRecoveryCodes
from .mfa_type import MfaType
from .mfa_factors import MfaFactors
Expand All @@ -220,10 +224,14 @@
from .billing_plan_dedicated_database_limits import BillingPlanDedicatedDatabaseLimits
from .billing_plan_supported_addons import BillingPlanSupportedAddons
from .block import Block
from .database_migration import DatabaseMigration
from .dedicated_database import DedicatedDatabase
from .database_status import DatabaseStatus
from .dedicated_database_member import DedicatedDatabaseMember
from .dedicated_database_operation import DedicatedDatabaseOperation
from .dedicated_database_operation_list import DedicatedDatabaseOperationList
from .dedicated_database_replicas import DedicatedDatabaseReplicas
from .proxy_invalidation import ProxyInvalidation
from .organization import Organization
from .backup_policy import BackupPolicy
from .policy_deny_aliased_email import PolicyDenyAliasedEmail
Expand Down Expand Up @@ -264,6 +272,7 @@
from .backup_archive_list import BackupArchiveList
from .backup_policy_list import BackupPolicyList
from .backup_restoration_list import BackupRestorationList
from .database_migration_list import DatabaseMigrationList
from .apps_list import AppsList
from .app_secret_list import AppSecretList
from .app_scope_list import AppScopeList
Expand Down Expand Up @@ -316,9 +325,11 @@
'TargetList',
'TransactionList',
'SpecificationList',
'EmbeddingList',
'InsightList',
'ReportList',
'Database',
'Embedding',
'Collection',
'AttributeList',
'AttributeString',
Expand Down Expand Up @@ -453,6 +464,7 @@
'PolicySessionLimit',
'PolicyUserLimit',
'PolicyMembershipPrivacy',
'PolicyMfaFactors',
'PlatformWeb',
'PlatformApple',
'PlatformAndroid',
Expand All @@ -470,6 +482,7 @@
'ProxyRule',
'EmailTemplate',
'MfaChallenge',
'MfaChallengeSecret',
'MfaRecoveryCodes',
'MfaType',
'MfaFactors',
Expand All @@ -493,10 +506,14 @@
'BillingPlanDedicatedDatabaseLimits',
'BillingPlanSupportedAddons',
'Block',
'DatabaseMigration',
'DedicatedDatabase',
'DatabaseStatus',
'DedicatedDatabaseMember',
'DedicatedDatabaseOperation',
'DedicatedDatabaseOperationList',
'DedicatedDatabaseReplicas',
'ProxyInvalidation',
'Organization',
'BackupPolicy',
'PolicyDenyAliasedEmail',
Expand Down Expand Up @@ -537,6 +554,7 @@
'BackupArchiveList',
'BackupPolicyList',
'BackupRestorationList',
'DatabaseMigrationList',
'AppsList',
'AppSecretList',
'AppScopeList',
Expand Down
16 changes: 8 additions & 8 deletions appwrite/models/billing_plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class BillingPlan(AppwriteModel):
Image Transformations
screenshotsgenerated : float
Screenshots generated
members : float
members : Optional[float]
Members
webhooks : float
Webhooks
Expand Down Expand Up @@ -84,7 +84,7 @@ class BillingPlan(AppwriteModel):
SMS authentications per month
domains : float
Custom domains
activitylogs : float
activitylogs : Optional[float]
Activity log days
usagelogs : float
Usage history days
Expand Down Expand Up @@ -132,13 +132,13 @@ class BillingPlan(AppwriteModel):
Does plan support restricting sign-ups to corporate email addresses only.
supportsprojectspecificroles : bool
Does plan support project-specific member roles.
backupsenabled : bool
backupsenabled : Optional[bool]
Does plan support backup policies.
usageperproject : bool
Whether usage addons are calculated per project.
supportedaddons : BillingPlanSupportedAddons
Supported addons for this plan
backuppolicies : float
backuppolicies : Optional[float]
How many policies does plan support
deploymentsize : float
Maximum function and site deployment size in MB
Expand All @@ -165,7 +165,7 @@ class BillingPlan(AppwriteModel):
storage: float = Field(..., alias='storage')
imagetransformations: float = Field(..., alias='imageTransformations')
screenshotsgenerated: float = Field(..., alias='screenshotsGenerated')
members: float = Field(..., alias='members')
members: Optional[float] = Field(default=None, alias='members')
webhooks: float = Field(..., alias='webhooks')
wafrules: float = Field(..., alias='wafRules')
projects: float = Field(..., alias='projects')
Expand All @@ -189,7 +189,7 @@ class BillingPlan(AppwriteModel):
topics: float = Field(..., alias='topics')
authphone: float = Field(..., alias='authPhone')
domains: float = Field(..., alias='domains')
activitylogs: float = Field(..., alias='activityLogs')
activitylogs: Optional[float] = Field(default=None, alias='activityLogs')
usagelogs: float = Field(..., alias='usageLogs')
usagelogsintervals: Optional[List[Any]] = Field(default=None, alias='usageLogsIntervals')
projectinactivitydays: float = Field(..., alias='projectInactivityDays')
Expand All @@ -213,10 +213,10 @@ class BillingPlan(AppwriteModel):
supportsfreeemailvalidation: bool = Field(..., alias='supportsFreeEmailValidation')
supportscorporateemailvalidation: bool = Field(..., alias='supportsCorporateEmailValidation')
supportsprojectspecificroles: bool = Field(..., alias='supportsProjectSpecificRoles')
backupsenabled: bool = Field(..., alias='backupsEnabled')
backupsenabled: Optional[bool] = Field(default=None, alias='backupsEnabled')
usageperproject: bool = Field(..., alias='usagePerProject')
supportedaddons: BillingPlanSupportedAddons = Field(..., alias='supportedAddons')
backuppolicies: float = Field(..., alias='backupPolicies')
backuppolicies: Optional[float] = Field(default=None, alias='backupPolicies')
deploymentsize: float = Field(..., alias='deploymentSize')
buildsize: float = Field(..., alias='buildSize')
databasesallowencrypt: bool = Field(..., alias='databasesAllowEncrypt')
Expand Down
8 changes: 4 additions & 4 deletions appwrite/models/billing_plan_addon.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ class BillingPlanAddon(AppwriteModel):

Attributes
----------
seats : BillingPlanAddonDetails
seats : Optional[BillingPlanAddonDetails]
Addon seats
projects : BillingPlanAddonDetails
projects : Optional[BillingPlanAddonDetails]
Addon projects
"""
seats: BillingPlanAddonDetails = Field(..., alias='seats')
projects: BillingPlanAddonDetails = Field(..., alias='projects')
seats: Optional[BillingPlanAddonDetails] = Field(default=None, alias='seats')
projects: Optional[BillingPlanAddonDetails] = Field(default=None, alias='projects')
4 changes: 2 additions & 2 deletions appwrite/models/billing_plan_addon_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class BillingPlanAddonDetails(AppwriteModel):
Addon limit
type : str
Addon type
currency : str
currency : Optional[str]
Price currency
price : float
Price
Expand All @@ -30,7 +30,7 @@ class BillingPlanAddonDetails(AppwriteModel):
planincluded: float = Field(..., alias='planIncluded')
limit: float = Field(..., alias='limit')
type: str = Field(..., alias='type')
currency: str = Field(..., alias='currency')
currency: Optional[str] = Field(default=None, alias='currency')
price: float = Field(..., alias='price')
value: float = Field(..., alias='value')
invoicedesc: str = Field(..., alias='invoiceDesc')
Loading