Name | realtime JSON |
Version |
2.7.0
JSON |
| download |
home_page | None |
Summary | None |
upload_time | 2025-07-28 18:54:22 |
maintainer | None |
docs_url | None |
author | Joel Lee |
requires_python | >=3.9 |
license | MIT |
keywords |
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
<br />
<p align="center">
<a href="https://supabase.io">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/supabase/supabase/main/packages/common/assets/images/supabase-logo-wordmark--dark.svg">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/supabase/supabase/main/packages/common/assets/images/supabase-logo-wordmark--light.svg">
<img alt="Supabase Logo" width="300" src="https://raw.githubusercontent.com/supabase/supabase/main/packages/common/assets/images/logo-preview.jpg">
</picture>
</a>
<h1 align="center">Supabase Realtime Client</h1>
<h3 align="center">Send ephemeral messages with <b>Broadcast</b>, track and synchronize state with <b>Presence</b>, and listen to database changes with <b>Postgres Change Data Capture (CDC)</b>.</h3>
<p align="center">
<a href="https://supabase.com/docs/guides/realtime">Guides</a>
·
<a href="https://supabase.com/docs/reference/python">Reference Docs</a>
·
<a href="https://multiplayer.dev">Multiplayer Demo</a>
</p>
</p>
# Overview
This client enables you to use the following Supabase Realtime's features:
- **Broadcast**: send ephemeral messages from client to clients with minimal latency. Use cases include sharing cursor positions between users.
- **Presence**: track and synchronize shared state across clients with the help of CRDTs. Use cases include tracking which users are currently viewing a specific webpage.
- **Postgres Change Data Capture (CDC)**: listen for changes in your PostgreSQL database and send them to clients.
# Usage
## Installing the Package
```bash
pip3 install realtime
```
## Creating a Channel
```python
import asyncio
from typing import Optional
from realtime import AsyncRealtimeClient, RealtimeSubscribeStates
async def main():
REALTIME_URL = "ws://localhost:4000/websocket"
API_KEY = "1234567890"
socket = AsyncRealtimeClient(REALTIME_URL, API_KEY)
channel = socket.channel("test-channel")
def _on_subscribe(status: RealtimeSubscribeStates, err: Optional[Exception]):
if status == RealtimeSubscribeStates.SUBSCRIBED:
print("Connected!")
elif status == RealtimeSubscribeStates.CHANNEL_ERROR:
print(f"There was an error subscribing to channel: {err.args}")
elif status == RealtimeSubscribeStates.TIMED_OUT:
print("Realtime server did not respond in time.")
elif status == RealtimeSubscribeStates.CLOSED:
print("Realtime channel was unexpectedly closed.")
await channel.subscribe(_on_subscribe)
```
### Notes:
- `REALTIME_URL` is `ws://localhost:4000/socket` when developing locally and `wss://<project_ref>.supabase.co/realtime/v1` when connecting to your Supabase project.
- `API_KEY` is a JWT whose claims must contain `exp` and `role` (existing database role).
- Channel name can be any `string`.
## Broadcast
Your client can send and receive messages based on the `event`.
```python
# Setup...
channel = client.channel(
"broadcast-test", {"config": {"broadcast": {"ack": False, "self": False}}}
)
await channel.on_broadcast("some-event", lambda payload: print(payload)).subscribe()
await channel.send_broadcast("some-event", {"hello": "world"})
```
### Notes:
- Setting `ack` to `true` means that the `channel.send` promise will resolve once server replies with acknowledgement that it received the broadcast message request.
- Setting `self` to `true` means that the client will receive the broadcast message it sent out.
- Setting `private` to `true` means that the client will use RLS to determine if the user can connect or not to a given channel.
## Presence
Your client can track and sync state that's stored in the channel.
```python
# Setup...
channel = client.channel(
"presence-test",
{
"config": {
"presence": {
"key": ""
}
}
}
)
channel.on_presence_sync(lambda: print("Online users: ", channel.presence_state()))
channel.on_presence_join(lambda new_presences: print("New users have joined: ", new_presences))
channel.on_presence_leave(lambda left_presences: print("Users have left: ", left_presences))
await channel.track({ 'user_id': 1 })
```
## Postgres CDC
Receive database changes on the client.
```python
# Setup...
channel = client.channel("db-changes")
channel.on_postgres_changes(
"*",
schema="public",
callback=lambda payload: print("All changes in public schema: ", payload),
)
channel.on_postgres_changes(
"INSERT",
schema="public",
table="messages",
callback=lambda payload: print("All inserts in messages table: ", payload),
)
channel.on_postgres_changes(
"UPDATE",
schema="public",
table="users",
filter="username=eq.Realtime",
callback=lambda payload: print(
"All updates on users table when username is Realtime: ", payload
),
)
channel.subscribe(
lambda status, err: status == RealtimeSubscribeStates.SUBSCRIBED
and print("Ready to receive database changes!")
)
```
## Get All Channels
You can see all the channels that your client has instantiated.
```python
# Setup...
client.get_channels()
```
## Cleanup
It is highly recommended that you clean up your channels after you're done with them.
- Remove a single channel
```python
# Setup...
channel = client.channel('some-channel-to-remove')
channel.subscribe()
await client.remove_channel(channel)
```
- Remove all channels
```python
# Setup...
channel1 = client.channel('a-channel-to-remove')
channel2 = client.channel('another-channel-to-remove')
await channel1.subscribe()
await channel2.subscribe()
await client.remove_all_channels()
```
## Credits
This repo draws heavily from [phoenix-js](https://github.com/phoenixframework/phoenix/tree/master/assets/js/phoenix).
## License
MIT.
Raw data
{
"_id": null,
"home_page": null,
"name": "realtime",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": null,
"author": "Joel Lee",
"author_email": "joel@joellee.org",
"download_url": "https://files.pythonhosted.org/packages/d3/ca/e408fbdb6b344bf529c7e8bf020372d21114fe538392c72089462edd26e5/realtime-2.7.0.tar.gz",
"platform": null,
"description": "<br />\n<p align=\"center\">\n <a href=\"https://supabase.io\">\n <picture>\n <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/main/packages/common/assets/images/supabase-logo-wordmark--dark.svg\">\n <source media=\"(prefers-color-scheme: light)\" srcset=\"https://raw.githubusercontent.com/supabase/supabase/main/packages/common/assets/images/supabase-logo-wordmark--light.svg\">\n <img alt=\"Supabase Logo\" width=\"300\" src=\"https://raw.githubusercontent.com/supabase/supabase/main/packages/common/assets/images/logo-preview.jpg\">\n </picture>\n </a>\n\n <h1 align=\"center\">Supabase Realtime Client</h1>\n\n <h3 align=\"center\">Send ephemeral messages with <b>Broadcast</b>, track and synchronize state with <b>Presence</b>, and listen to database changes with <b>Postgres Change Data Capture (CDC)</b>.</h3>\n\n <p align=\"center\">\n <a href=\"https://supabase.com/docs/guides/realtime\">Guides</a>\n \u00b7\n <a href=\"https://supabase.com/docs/reference/python\">Reference Docs</a>\n \u00b7\n <a href=\"https://multiplayer.dev\">Multiplayer Demo</a>\n </p>\n</p>\n\n# Overview\n\nThis client enables you to use the following Supabase Realtime's features:\n\n- **Broadcast**: send ephemeral messages from client to clients with minimal latency. Use cases include sharing cursor positions between users.\n- **Presence**: track and synchronize shared state across clients with the help of CRDTs. Use cases include tracking which users are currently viewing a specific webpage.\n- **Postgres Change Data Capture (CDC)**: listen for changes in your PostgreSQL database and send them to clients.\n\n# Usage\n\n## Installing the Package\n\n```bash\npip3 install realtime\n```\n\n## Creating a Channel\n\n```python\nimport asyncio\nfrom typing import Optional\n\nfrom realtime import AsyncRealtimeClient, RealtimeSubscribeStates\n\n\nasync def main():\n REALTIME_URL = \"ws://localhost:4000/websocket\"\n API_KEY = \"1234567890\"\n\n socket = AsyncRealtimeClient(REALTIME_URL, API_KEY)\n channel = socket.channel(\"test-channel\")\n\n def _on_subscribe(status: RealtimeSubscribeStates, err: Optional[Exception]):\n if status == RealtimeSubscribeStates.SUBSCRIBED:\n print(\"Connected!\")\n elif status == RealtimeSubscribeStates.CHANNEL_ERROR:\n print(f\"There was an error subscribing to channel: {err.args}\")\n elif status == RealtimeSubscribeStates.TIMED_OUT:\n print(\"Realtime server did not respond in time.\")\n elif status == RealtimeSubscribeStates.CLOSED:\n print(\"Realtime channel was unexpectedly closed.\")\n\n await channel.subscribe(_on_subscribe)\n```\n\n### Notes:\n\n- `REALTIME_URL` is `ws://localhost:4000/socket` when developing locally and `wss://<project_ref>.supabase.co/realtime/v1` when connecting to your Supabase project.\n- `API_KEY` is a JWT whose claims must contain `exp` and `role` (existing database role).\n- Channel name can be any `string`.\n\n## Broadcast\n\nYour client can send and receive messages based on the `event`.\n\n```python\n# Setup...\n\nchannel = client.channel(\n \"broadcast-test\", {\"config\": {\"broadcast\": {\"ack\": False, \"self\": False}}}\n)\n\nawait channel.on_broadcast(\"some-event\", lambda payload: print(payload)).subscribe()\nawait channel.send_broadcast(\"some-event\", {\"hello\": \"world\"})\n```\n\n### Notes:\n\n- Setting `ack` to `true` means that the `channel.send` promise will resolve once server replies with acknowledgement that it received the broadcast message request.\n- Setting `self` to `true` means that the client will receive the broadcast message it sent out.\n- Setting `private` to `true` means that the client will use RLS to determine if the user can connect or not to a given channel.\n\n## Presence\n\nYour client can track and sync state that's stored in the channel.\n\n```python\n# Setup...\n\nchannel = client.channel(\n \"presence-test\",\n {\n \"config\": {\n \"presence\": {\n \"key\": \"\"\n }\n }\n }\n)\n\nchannel.on_presence_sync(lambda: print(\"Online users: \", channel.presence_state()))\nchannel.on_presence_join(lambda new_presences: print(\"New users have joined: \", new_presences))\nchannel.on_presence_leave(lambda left_presences: print(\"Users have left: \", left_presences))\n\nawait channel.track({ 'user_id': 1 })\n```\n\n## Postgres CDC\n\nReceive database changes on the client.\n\n```python\n# Setup...\n\nchannel = client.channel(\"db-changes\")\n\nchannel.on_postgres_changes(\n \"*\",\n schema=\"public\",\n callback=lambda payload: print(\"All changes in public schema: \", payload),\n)\n\nchannel.on_postgres_changes(\n \"INSERT\",\n schema=\"public\",\n table=\"messages\",\n callback=lambda payload: print(\"All inserts in messages table: \", payload),\n)\n\nchannel.on_postgres_changes(\n \"UPDATE\",\n schema=\"public\",\n table=\"users\",\n filter=\"username=eq.Realtime\",\n callback=lambda payload: print(\n \"All updates on users table when username is Realtime: \", payload\n ),\n)\n\nchannel.subscribe(\n lambda status, err: status == RealtimeSubscribeStates.SUBSCRIBED\n and print(\"Ready to receive database changes!\")\n)\n```\n\n## Get All Channels\n\nYou can see all the channels that your client has instantiated.\n\n```python\n# Setup...\n\nclient.get_channels()\n```\n\n## Cleanup\n\nIt is highly recommended that you clean up your channels after you're done with them.\n\n- Remove a single channel\n\n```python\n# Setup...\n\nchannel = client.channel('some-channel-to-remove')\n\nchannel.subscribe()\n\nawait client.remove_channel(channel)\n```\n\n- Remove all channels\n\n```python\n# Setup...\n\nchannel1 = client.channel('a-channel-to-remove')\nchannel2 = client.channel('another-channel-to-remove')\n\nawait channel1.subscribe()\nawait channel2.subscribe()\n\nawait client.remove_all_channels()\n```\n\n## Credits\n\nThis repo draws heavily from [phoenix-js](https://github.com/phoenixframework/phoenix/tree/master/assets/js/phoenix).\n\n## License\n\nMIT.\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": null,
"version": "2.7.0",
"project_urls": null,
"split_keywords": [],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "d207a5c7aef12f9a3497f5ad77157a37915645861e8b23b89b2ad4b0f11b48ad",
"md5": "5a3cbe0e96858344851a904fbf351010",
"sha256": "d55a278803529a69d61c7174f16563a9cfa5bacc1664f656959694481903d99c"
},
"downloads": -1,
"filename": "realtime-2.7.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "5a3cbe0e96858344851a904fbf351010",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 22409,
"upload_time": "2025-07-28T18:54:21",
"upload_time_iso_8601": "2025-07-28T18:54:21.383797Z",
"url": "https://files.pythonhosted.org/packages/d2/07/a5c7aef12f9a3497f5ad77157a37915645861e8b23b89b2ad4b0f11b48ad/realtime-2.7.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "d3cae408fbdb6b344bf529c7e8bf020372d21114fe538392c72089462edd26e5",
"md5": "b7dee7e78006e8a82b00441ec156239d",
"sha256": "6b9434eeba8d756c8faf94fc0a32081d09f250d14d82b90341170602adbb019f"
},
"downloads": -1,
"filename": "realtime-2.7.0.tar.gz",
"has_sig": false,
"md5_digest": "b7dee7e78006e8a82b00441ec156239d",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 18860,
"upload_time": "2025-07-28T18:54:22",
"upload_time_iso_8601": "2025-07-28T18:54:22.949381Z",
"url": "https://files.pythonhosted.org/packages/d3/ca/e408fbdb6b344bf529c7e8bf020372d21114fe538392c72089462edd26e5/realtime-2.7.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-28 18:54:22",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "realtime"
}