Skip to content
Closed
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Virtual environments
.venv/
venv/
env/

# Python bytecode
__pycache__/
*.py[cod]

# Packaging / build artifacts
build/
dist/
*.egg-info/
.eggs/

# Test and tooling caches
.pytest_cache/
.mypy_cache/
.ruff_cache/
.coverage
htmlcov/

# Editor and OS files
.idea/
.vscode/
.DS_Store
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@

* Breaking: `tables_db`, `documents_db` and `vectors_db` `create` and `update` take `description` before `specification`
* Breaking: `functions.update` takes `description` before `email_enabled`
* Breaking: every service method is now a coroutine and must be awaited; `Client.call` and `Client.chunked_upload` are async as well
* Breaking: the SDK now requires Python 3.11 or later
* Breaking: `requests` was replaced by `httpx2`, changing the transport and connection pooling behaviour
* Breaking: `on_progress` callbacks may now be coroutine functions and are awaited when they are
* Added: `create_query` on `databases`, `documents_db` and `tables_db` to send list queries in the request body
* Added: `account.list_memberships`
* Added: `Client.aclose()` and async context manager support for `Client`
* Added: optional `description` on create and update for databases, collections, tables, attributes, columns, indexes, buckets, functions, sites, variables, topics, webhooks and keys
* Added: `description` on the matching models
* Added: `total` on list methods in `activities`, `backups`, `domains`, `mongo`, `mysql` and `postgresql`
Expand Down
116 changes: 82 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Appwrite is an open-source backend as a service server that abstracts and simpli

## Installation

Requires Python 3.9 or later. Install the [`appwrite`](https://pypi.org/project/appwrite/) package from PyPI:
Requires Python 3.11 or later. Install the [`appwrite`](https://pypi.org/project/appwrite/) package from PyPI:

```bash
pip install appwrite
Expand All @@ -27,6 +27,8 @@ uv add appwrite

## Getting started

Every API call is asynchronous, so every service method returns a coroutine you `await`.

### Initialize the client

Create a client with your Appwrite endpoint, project ID and an [API key](https://appwrite.io/docs/partners/project/api-keys). Find the endpoint and project ID in your project's **Settings** page, and create an API key with only the scopes you need under **API keys** in the project sidebar.
Expand All @@ -44,24 +46,31 @@ API keys grant server-level access to your project. Keep them out of client-side

### Make a request

Create a service object with the client and call any of its methods. Every method returns a typed Pydantic model, so response fields are available as attributes.
Create a service object with the client and await any of its methods. Every method returns a typed Pydantic model, so response fields are available as attributes.

```python
import asyncio

from appwrite.id import ID
from appwrite.services.users import Users

users = Users(client)

user = users.create(
user_id=ID.unique(),
email='email@example.com',
password='password',
name="Walter O'Brien",
)
async def main():
users = Users(client)

user = await users.create(
user_id=ID.unique(),
email='email@example.com',
password='password',
name="Walter O'Brien",
)

print(user.id)
print(user.name)
print(user.to_dict())

print(user.id)
print(user.name)
print(user.to_dict())

asyncio.run(main())
```

See the [API reference](https://appwrite.io/docs/references/cloud/server-python/users) for every service and method.
Expand All @@ -71,6 +80,7 @@ See the [API reference](https://appwrite.io/docs/references/cloud/server-python/
Use `TablesDB` to read and write rows. Pass a Pydantic model as `model_type` to get typed row data back; without it, `row.data` is a `dict`.

```python
import asyncio
from typing import Optional

from pydantic import BaseModel
Expand All @@ -86,41 +96,79 @@ class Post(BaseModel):
excerpt: Optional[str] = None


tables_db = TablesDB(client)
async def main():
tables_db = TablesDB(client)

row = await tables_db.create_row(
database_id='<DATABASE_ID>',
table_id='<TABLE_ID>',
row_id=ID.unique(),
data={'title': 'Hello, world', 'published': True},
model_type=Post,
)

row = tables_db.create_row(
database_id='<DATABASE_ID>',
table_id='<TABLE_ID>',
row_id=ID.unique(),
data={'title': 'Hello, world', 'published': True},
model_type=Post,
)
print(row.id)
print(row.data.title)

print(row.id)
print(row.data.title)
result = await tables_db.list_rows(
database_id='<DATABASE_ID>',
table_id='<TABLE_ID>',
queries=[Query.equal('published', True), Query.limit(25)],
model_type=Post,
)

result = tables_db.list_rows(
database_id='<DATABASE_ID>',
table_id='<TABLE_ID>',
queries=[Query.equal('published', True), Query.limit(25)],
model_type=Post,
)
for row in result.rows:
print(row.data.title)

for row in result.rows:
print(row.data.title)

asyncio.run(main())
```

### Handle errors

Failed requests raise `AppwriteException`, which carries `message`, `code`, `type` and `response`.

```python
import asyncio

from appwrite.exception import AppwriteException
from appwrite.services.users import Users


async def main():
users = Users(client)

try:
user = await users.get(user_id='<USER_ID>')
except AppwriteException as error:
print(error.code, error.type, error.message)


asyncio.run(main())
```

### Close the client

The client keeps a pooled HTTP connection open. Close it when you are done, or use it as an async context manager.

```python
async def main():
await client.aclose()


asyncio.run(main())
```

```python
from appwrite.client import Client


async def main():
async with Client() as client:
...


try:
user = users.get(user_id='<USER_ID>')
except AppwriteException as error:
print(error.code, error.type, error.message)
asyncio.run(main())
```

### Self-hosted Appwrite
Expand Down
Loading
Loading