Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Change Log

## 27.2.0

* Updated: `project.list_environments`, `project.create_environment`, `project.get_environment`, `project.update_environment` return `Environment` models instead of `Project`
* Added: `account.create_device`, `account.get_device`, `account.delete_device` and `account.update_device_session`, and the `Device` model
* Added: `project.update_account_devices_policy`, `ProjectPolicyId.ACCOUNT_DEVICES` and the `PolicyAccountDevices` model
* Added: `project.update_o_auth2_vipps`, `project.update_o_auth2_vipps_sandbox` and the `OAuth2Vipps` model
* Added: `OAuthProvider.VIPPS` and `OAuthProvider.VIPPSSANDBOX`
* Added: `proxy.update_function_rule`, `proxy.update_redirect_rule` and `proxy.update_site_rule`
* Added: optional `schedule` on `waf` rule create and update methods and on `WafRule*` models
* Added: `project.get_prefs` and `project.update_prefs` for project preferences
* Added: `Client.set_environment` to act in a project environment
* Added: `AppwriteMigrationResource.PROJECT_PREFERENCES` to migrate project preferences
* Added: `monitors.read`, `monitors.write`, `alerts.read`, `alerts.write`, `reviews.read` and `reviews.write` to `ProjectKeyScopes`
* Added: `Organization.budgetnotify`, `budgetcritical` and `educationexpiresat`
* Added: `Project.environmentid`, `Session.username` and `ActivityEvent.reason`
* Added: `ProxyRule.expireat` and `certificatestatus`
* Updated: requests send response format `2.7.1`; README targets Appwrite 2.7.x

## 27.1.0

* Added: `migrations` service to run Appwrite, Firebase, NHost, Supabase, CSV and JSON migrations, plus retries and listing
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Appwrite Python SDK

![License](https://img.shields.io/badge/license-BSD--3--Clause-blue.svg?style=flat-square)
![Version](https://img.shields.io/badge/api%20version-2.6.2-blue.svg?style=flat-square)
![Version](https://img.shields.io/badge/api%20version-2.7.1-blue.svg?style=flat-square)
[![X Account](https://img.shields.io/badge/follow-%40appwrite-000000?logo=x&style=flat-square)](https://x.com/appwrite)
[![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord)

**This SDK targets Appwrite server version 2.6.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.7.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)

Expand Down
13 changes: 10 additions & 3 deletions appwrite/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ def __init__(self):
self._endpoint = 'https://cloud.appwrite.io/v1'
self._global_headers = {
'content-type': '',
'user-agent': f'AppwritePythonSDK/27.1.0 ({platform.uname().system}; {platform.uname().version}; {platform.uname().machine})',
'user-agent': f'AppwritePythonSDK/27.2.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': '27.1.0',
'X-Appwrite-Response-Format': '2.6.2',
'x-sdk-version': '27.2.0',
'X-Appwrite-Response-Format': '2.7.1',
}
self._config = {}

Expand Down Expand Up @@ -89,6 +89,13 @@ def set_locale(self, value):
self._config['locale'] = value
return self

def set_environment(self, value):
"""The ID of the project environment to act in, alongside the project ID. Used with Appwrite Cloud projects that have environments."""

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

def set_session(self, value):
"""The user session to authenticate with"""

Expand Down
1 change: 1 addition & 0 deletions appwrite/enums/appwrite_migration_resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class AppwriteMigrationResource(Enum):
PROJECT_VARIABLE = "project-variable"
PROJECT_PROTOCOLS = "project-protocols"
PROJECT_LABELS = "project-labels"
PROJECT_PREFERENCES = "project-preferences"
PROJECT_SERVICES = "project-services"
PROJECT_EMAIL_TEMPLATE = "project-email-template"
PROJECT_ENVIRONMENT = "project-environment"
Expand Down
2 changes: 2 additions & 0 deletions appwrite/enums/o_auth_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class OAuthProvider(Enum):
TRADESHIFT = "tradeshift"
TRADESHIFTBOX = "tradeshiftBox"
TWITCH = "twitch"
VIPPS = "vipps"
VIPPSSANDBOX = "vippsSandbox"
WEBFLOW = "webflow"
WORDPRESS = "wordpress"
X = "x"
Expand Down
6 changes: 6 additions & 0 deletions appwrite/enums/project_key_scopes.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ class ProjectKeyScopes(Enum):
RULES_WRITE = "rules.write"
WEBHOOKS_READ = "webhooks.read"
WEBHOOKS_WRITE = "webhooks.write"
MONITORS_READ = "monitors.read"
MONITORS_WRITE = "monitors.write"
ALERTS_READ = "alerts.read"
ALERTS_WRITE = "alerts.write"
LOCALE_READ = "locale.read"
AVATARS_READ = "avatars.read"
AVATARS_WRITE = "avatars.write"
Expand All @@ -105,6 +109,8 @@ class ProjectKeyScopes(Enum):
INSIGHTS_WRITE = "insights.write"
REPORTS_READ = "reports.read"
REPORTS_WRITE = "reports.write"
REVIEWS_READ = "reviews.read"
REVIEWS_WRITE = "reviews.write"
PRESENCES_READ = "presences.read"
PRESENCES_WRITE = "presences.write"
DEDICATEDDATABASES_EXECUTE = "dedicatedDatabases.execute"
Expand Down
2 changes: 2 additions & 0 deletions appwrite/enums/project_o_auth_provider_id.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class ProjectOAuthProviderId(Enum):
TRADESHIFT = "tradeshift"
TRADESHIFTBOX = "tradeshiftBox"
TWITCH = "twitch"
VIPPS = "vipps"
VIPPSSANDBOX = "vippsSandbox"
WEBFLOW = "webflow"
WORDPRESS = "wordpress"
X = "x"
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 @@ -21,3 +21,4 @@ class ProjectPolicyId(Enum):
DENY_CORPORATE_EMAIL = "deny-corporate-email"
DENY_REALTIME_GUESTS = "deny-realtime-guests"
PASSKEY = "passkey"
ACCOUNT_DEVICES = "account-devices"
10 changes: 10 additions & 0 deletions appwrite/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
from .account import Account
from .preferences import Preferences
from .session import Session
from .device import Device
from .identity import Identity
from .token import Token
from .jwt import Jwt
Expand Down Expand Up @@ -175,6 +176,7 @@
from .o_auth2_oidc import OAuth2Oidc
from .o_auth2_okta import OAuth2Okta
from .o_auth2_kick import OAuth2Kick
from .o_auth2_vipps import OAuth2Vipps
from .o_auth2_apple import OAuth2Apple
from .o_auth2_microsoft import OAuth2Microsoft
from .o_auth2_resend import OAuth2Resend
Expand All @@ -200,6 +202,7 @@
from .policy_deny_free_email import PolicyDenyFreeEmail
from .policy_deny_corporate_email import PolicyDenyCorporateEmail
from .policy_deny_realtime_guests import PolicyDenyRealtimeGuests
from .policy_account_devices import PolicyAccountDevices
from .platform_web import PlatformWeb
from .platform_apple import PlatformApple
from .platform_android import PlatformAndroid
Expand Down Expand Up @@ -273,6 +276,8 @@
from .dedicated_database_pooler import DedicatedDatabasePooler
from .postgres_extension import PostgresExtension
from .program import Program
from .environment import Environment
from .environment_list import EnvironmentList
from .backup_restoration import BackupRestoration
from .dedicated_database_restoration_list import DedicatedDatabaseRestorationList
from .dedicated_database_specification import DedicatedDatabaseSpecification
Expand Down Expand Up @@ -435,6 +440,7 @@
'Account',
'Preferences',
'Session',
'Device',
'Identity',
'Token',
'Jwt',
Expand Down Expand Up @@ -502,6 +508,7 @@
'OAuth2Oidc',
'OAuth2Okta',
'OAuth2Kick',
'OAuth2Vipps',
'OAuth2Apple',
'OAuth2Microsoft',
'OAuth2Resend',
Expand All @@ -527,6 +534,7 @@
'PolicyDenyFreeEmail',
'PolicyDenyCorporateEmail',
'PolicyDenyRealtimeGuests',
'PolicyAccountDevices',
'PlatformWeb',
'PlatformApple',
'PlatformAndroid',
Expand Down Expand Up @@ -600,6 +608,8 @@
'DedicatedDatabasePooler',
'PostgresExtension',
'Program',
'Environment',
'EnvironmentList',
'BackupRestoration',
'DedicatedDatabaseRestorationList',
'DedicatedDatabaseSpecification',
Expand Down
5 changes: 5 additions & 0 deletions appwrite/models/activity_event.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class ActivityEvent(AppwriteModel):
Name of the SDK that triggered the event.
sdkversion : str
Version of the SDK that triggered the event.
reason : str
Why the actor made the request, as sent in the `X-Appwrite-Reason` header. Empty when no reason was given.
"""

id: str = Field(..., alias='$id')
Expand Down Expand Up @@ -99,6 +101,7 @@ class ActivityEvent(AppwriteModel):
hostname: str = Field(..., alias='hostname')
sdk: str = Field(..., alias='sdk')
sdkversion: str = Field(..., alias='sdkVersion')
reason: str = Field(..., alias='reason')

@model_validator(mode='before')
@classmethod
Expand Down Expand Up @@ -165,4 +168,6 @@ def _apply_defaults(cls, data: Any) -> Any:
data['sdk'] = ''
if 'sdkVersion' not in data and 'sdkversion' not in data:
data['sdkVersion'] = ''
if 'reason' not in data:
data['reason'] = ''
return data
59 changes: 59 additions & 0 deletions appwrite/models/device.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from typing import Any, Dict, List, Optional, Union, cast
from pydantic import Field, PrivateAttr, model_validator

from .base_model import AppwriteModel
from .session import Session


class Device(AppwriteModel):
"""
Device

Attributes
----------
id : str
Device ID.
createdat : str
Device creation date in ISO 8601 format.
updatedat : str
Device update date in ISO 8601 format.
expire : str
Device expiration date in ISO 8601 format.
activesessionid : str
ID of the session that is currently active on the device. Empty when no session is active, for example right after the active session was deleted.
sessions : List[Session]
List of sessions the device holds. Switch between them to change the active account.
secret : str
Secret used to authenticate the device. Carried by the device cookie; only included in the response if the request was made with an API key.
"""

id: str = Field(..., alias='$id')
createdat: str = Field(..., alias='$createdAt')
updatedat: str = Field(..., alias='$updatedAt')
expire: str = Field(..., alias='expire')
activesessionid: str = Field(..., alias='activeSessionId')
sessions: List[Session] = Field(..., alias='sessions')
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 '$createdAt' not in data and 'createdat' not in data:
data['$createdAt'] = ''
if '$updatedAt' not in data and 'updatedat' not in data:
data['$updatedAt'] = ''
if 'expire' not in data:
data['expire'] = ''
if 'activeSessionId' not in data and 'activesessionid' not in data:
data['activeSessionId'] = ''
if 'sessions' not in data:
data['sessions'] = []
if 'secret' not in data:
data['secret'] = ''
return data
48 changes: 48 additions & 0 deletions appwrite/models/environment.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from typing import Any, Dict, List, Optional, Union, cast
from pydantic import Field, PrivateAttr, model_validator

from .base_model import AppwriteModel


class Environment(AppwriteModel):
"""
Environment

Attributes
----------
id : str
Environment ID, as passed in the X-Appwrite-Environment header.
createdat : str
Environment creation date in ISO 8601 format.
updatedat : str
Environment update date in ISO 8601 format.
projectid : str
ID of the project the environment belongs to, as passed in the X-Appwrite-Project header.
name : str
Environment name.
"""

id: str = Field(..., alias='$id')
createdat: str = Field(..., alias='$createdAt')
updatedat: str = Field(..., alias='$updatedAt')
projectid: str = Field(..., alias='projectId')
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 '$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'] = ''
return data
34 changes: 34 additions & 0 deletions appwrite/models/environment_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
from typing import Any, Dict, List, Optional, Union, cast
from pydantic import Field, PrivateAttr, model_validator

from .base_model import AppwriteModel
from .environment import Environment


class EnvironmentList(AppwriteModel):
"""
Environments list

Attributes
----------
total : float
Total number of environments that matched your query.
environments : List[Environment]
List of environments.
"""

total: float = Field(..., alias='total')
environments: List[Environment] = Field(..., alias='environments')

@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 'environments' not in data:
data['environments'] = []
return data
4 changes: 3 additions & 1 deletion appwrite/models/o_auth2_provider_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
from .o_auth2_cloudflare import OAuth2Cloudflare
from .o_auth2_tik_tok import OAuth2TikTok
from .o_auth2_kakao import OAuth2Kakao
from .o_auth2_vipps import OAuth2Vipps


class OAuth2ProviderList(AppwriteModel):
Expand All @@ -59,7 +60,7 @@ class OAuth2ProviderList(AppwriteModel):
----------
total : float
Total number of OAuth2 providers in the given project.
providers : List[Union[OAuth2Github, OAuth2Discord, OAuth2Figma, OAuth2Dropbox, OAuth2Dailymotion, OAuth2Bitbucket, OAuth2Bitly, OAuth2Box, OAuth2Autodesk, OAuth2Google, OAuth2Zoom, OAuth2Zoho, OAuth2Yandex, OAuth2X, OAuth2WordPress, OAuth2Webflow, OAuth2Twitch, OAuth2Stripe, OAuth2Spotify, OAuth2Slack, OAuth2Podio, OAuth2Notion, OAuth2Salesforce, OAuth2Yahoo, OAuth2Linkedin, OAuth2Disqus, OAuth2Amazon, OAuth2Etsy, OAuth2Facebook, OAuth2Tradeshift, OAuth2Paypal, OAuth2Gitlab, OAuth2Appwrite, OAuth2Authentik, OAuth2Auth0, OAuth2FusionAuth, OAuth2Keycloak, OAuth2Oidc, OAuth2Apple, OAuth2Okta, OAuth2Kick, OAuth2Microsoft, OAuth2HuggingFace, OAuth2Resend, OAuth2Cloudflare, OAuth2TikTok, OAuth2Kakao]]
providers : List[Union[OAuth2Github, OAuth2Discord, OAuth2Figma, OAuth2Dropbox, OAuth2Dailymotion, OAuth2Bitbucket, OAuth2Bitly, OAuth2Box, OAuth2Autodesk, OAuth2Google, OAuth2Zoom, OAuth2Zoho, OAuth2Yandex, OAuth2X, OAuth2WordPress, OAuth2Webflow, OAuth2Twitch, OAuth2Stripe, OAuth2Spotify, OAuth2Slack, OAuth2Podio, OAuth2Notion, OAuth2Salesforce, OAuth2Yahoo, OAuth2Linkedin, OAuth2Disqus, OAuth2Amazon, OAuth2Etsy, OAuth2Facebook, OAuth2Tradeshift, OAuth2Paypal, OAuth2Gitlab, OAuth2Appwrite, OAuth2Authentik, OAuth2Auth0, OAuth2FusionAuth, OAuth2Keycloak, OAuth2Oidc, OAuth2Apple, OAuth2Okta, OAuth2Kick, OAuth2Microsoft, OAuth2HuggingFace, OAuth2Resend, OAuth2Cloudflare, OAuth2TikTok, OAuth2Kakao, OAuth2Vipps]]
List of OAuth2 providers.
"""

Expand Down Expand Up @@ -113,6 +114,7 @@ class OAuth2ProviderList(AppwriteModel):
OAuth2Cloudflare,
OAuth2TikTok,
OAuth2Kakao,
OAuth2Vipps,
]
] = Field(..., alias='providers')

Expand Down
Loading