Skip to content

Commit f7a3804

Browse files
authored
chore: misc small changes (#1239)
1 parent 7d273b2 commit f7a3804

File tree

13 files changed

+141
-81
lines changed

13 files changed

+141
-81
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
.PHONY: ci, default, pre-commit, clean, start-infra, stop-infra
1+
.PHONY: ci, default, clean, start-infra, stop-infra
22

33
PACKAGES := functions realtime storage auth postgrest supabase
44
FORALL_PKGS = $(foreach pkg, $(PACKAGES), $(pkg).$(1))

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,15 @@ cd supabase-py
3333

3434
This repository relies on the following dependencies for development:
3535
- `uv` for python project management.
36-
- `make` for command running.
36+
- `make` for running project commands.
3737
- `docker` for both `postgrest` and `auth` test containers.
3838
- `supabase-cli` for both `storage` and `realtime` test containers.
3939

4040
All of these dependencies are included in the nix shell environment, through `flake.nix`. If you've got `nix` installed, you may prefer to use it through `nix develop`.
4141

4242
### Use a Virtual Environment
4343

44-
We recommend using a virtual environment, preferrably through `uv`, given it is currently the only tool that understands the workspace setup (you can read more about it in [the uv docs](https://docs.astral.sh/uv/concepts/projects/workspaces/)).
44+
We recommend using a virtual environment, preferably through `uv`, given it is currently the only tool that understands the workspace setup (you can read more about it in [the uv docs](https://docs.astral.sh/uv/concepts/projects/workspaces/)).
4545

4646
```
4747
uv venv supabase-py
@@ -53,7 +53,7 @@ If you're using nix, the generated `python` executable should have the correct d
5353

5454
### Running tests and other commands
5555

56-
We use `make` to store and run the relevant commands. The structure is setup such that each sub package can individually set its command in its own `Makefile`, and the job of the main `Makefile` is just coordinate calling each of them.
56+
We use `make` to store and run the relevant commands. The structure is set up such that each sub package can individually set its command in its own `Makefile`, and the job of the main `Makefile` is just coordinate calling each of them.
5757

5858
For instance, in order to run all tests of all packages, you should use the following root command
5959
```bash
@@ -70,11 +70,11 @@ To run each of the packages' tests in parallel. This should be generally faster
7070
Other relevant commands include
7171
```bash
7272
make install-hooks # install all commit hooks into the local .git folder
73-
make stop-infra # stops all running containers from all packages
74-
make clean # delete all intermediary files created by testing
73+
make stop-infra # stops all running containers from all packages
74+
make clean # delete all intermediary files created by testing
7575
```
76-
All the sub packages command are available from the main root by prefixing the command with `{package_name}.`. Examples:
76+
All the subpackages command are available from the main root by prefixing the command with `{package_name}.`. Examples:
7777
```bash
7878
make realtime.tests # run only realtime tests
79-
make storage.clean # delete temporary files only in the storage package
79+
make storage.clean # delete temporary files only in the storage package
8080
```

src/functions/pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ tests = [
3232
lints = [
3333
"unasync>=0.6.0",
3434
"ruff >=0.12.1",
35-
"pre-commit >=3.4,<5.0",
3635
"python-lsp-server (>=1.12.2,<2.0.0)",
3736
"pylsp-mypy (>=0.7.0,<0.8.0)",
3837
"python-lsp-ruff (>=2.2.2,<3.0.0)",

src/postgrest/pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ test = [
4141
"unasync >= 0.6.0",
4242
]
4343
lints = [
44-
"pre-commit >=4.2.0",
4544
"ruff >=0.12.1",
4645
"python-lsp-server (>=1.12.2,<2.0.0)",
4746
"pylsp-mypy (>=0.7.0,<0.8.0)",

src/realtime/Makefile

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,38 @@
1-
.PHONY: pytest pre-commit mypy tests infra stop-infra
1+
help::
2+
@echo "Available commands"
3+
@echo " help -- (default) print this message"
4+
5+
tests: mypy pytest
6+
help::
7+
@echo " tests -- run all tests for realtime package"
28

39
mypy:
4-
uv run --package realtime mypy src/realtime
10+
uv run --package realtime mypy src/realtime tests
11+
help::
12+
@echo " pytest -- run mypy on realtime package"
13+
14+
pytest: start-infra
15+
uv run --package realtime pytest --cov=realtime --cov-report=xml --cov-report=html -vv
16+
help::
17+
@echo " pytest -- run pytest on realtime package"
518

619
start-infra:
720
supabase start --workdir infra -x studio,mailpit,edge-runtime,logflare,vector,supavisor,imgproxy,storage-api
21+
help::
22+
@echo " stop-infra -- start containers for tests"
823

924
stop-infra:
1025
supabase --workdir infra stop
11-
12-
tests: mypy pytest
13-
14-
pytest: start-infra
15-
uv run --package realtime pytest --cov=realtime --cov-report=xml --cov-report=html -vv
26+
help::
27+
@echo " stop-infra -- stop containers for tests"
1628

1729
clean:
1830
rm -rf htmlcov .pytest_cache .mypy_cache .ruff_cache
1931
rm -f .coverage coverage.xml
32+
help::
33+
@echo " clean -- clean intermediary files generated by tests"
2034

2135
build:
2236
uv build --package realtime
37+
help::
38+
@echo " build -- invoke uv build on realtime package"

src/realtime/pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ tests = [
3333
"pytest-asyncio >= 1.0.0",
3434
]
3535
lints = [
36-
"pre-commit >= 4.2.0",
3736
"ruff >= 0.12.1",
3837
"python-lsp-server (>=1.12.2,<2.0.0)",
3938
"pylsp-mypy (>=0.7.0,<0.8.0)",

src/realtime/src/realtime/_async/timer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77

88
class AsyncTimer:
9-
def __init__(self, callback: Callable, timer_calc: Callable[[int], int]):
9+
def __init__(self, callback: Callable, timer_calc: Callable[[int], float]):
1010
self.callback = callback
1111
self.timer_calc = timer_calc
1212
self.timer: Optional[asyncio.Task] = None

src/realtime/src/realtime/py.typed

Whitespace-only changes.

src/realtime/tests/test_connection.py

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,14 @@
55
import aiohttp
66
import pytest
77
from dotenv import load_dotenv
8+
from pydantic import BaseModel
89

9-
from realtime import AsyncRealtimeChannel, AsyncRealtimeClient, RealtimeSubscribeStates
10+
from realtime import (
11+
AsyncRealtimeChannel,
12+
AsyncRealtimeClient,
13+
RealtimePostgresChangesListenEvent,
14+
RealtimeSubscribeStates,
15+
)
1016
from realtime.message import Message
1117
from realtime.types import DEFAULT_HEARTBEAT_INTERVAL, DEFAULT_TIMEOUT, ChannelEvents
1218

@@ -27,6 +33,14 @@ def socket() -> AsyncRealtimeClient:
2733
return AsyncRealtimeClient(url, key)
2834

2935

36+
class SignupMessageResponse(BaseModel):
37+
access_token: str
38+
token_type: str
39+
expires_in: int
40+
expires_at: int
41+
refresh_token: str
42+
43+
3044
async def access_token() -> str:
3145
url = f"{URL}/auth/v1/signup"
3246
headers = {"apikey": ANON_KEY, "Content-Type": "application/json"}
@@ -39,8 +53,11 @@ async def access_token() -> str:
3953
async with aiohttp.ClientSession() as session:
4054
async with session.post(url, headers=headers, json=data) as response:
4155
if response.status == 200:
42-
json_response = await response.json()
43-
return json_response.get("access_token")
56+
response_content = await response.read()
57+
signup_response = SignupMessageResponse.model_validate_json(
58+
response_content
59+
)
60+
return signup_response.access_token
4461
else:
4562
raise Exception(
4663
f"Failed to get access token. Status: {response.status}"
@@ -67,14 +84,20 @@ async def test_broadcast_events(socket: AsyncRealtimeClient):
6784
await socket.connect()
6885

6986
channel = socket.channel(
70-
"test-broadcast", params={"config": {"broadcast": {"self": True}}}
87+
"test-broadcast",
88+
params={
89+
"config": {
90+
"broadcast": {"self": True, "ack": True},
91+
"presence": {"enabled": True, "key": ""},
92+
"private": False,
93+
}
94+
},
7195
)
7296
received_events = []
7397

7498
semaphore = asyncio.Semaphore(0)
7599

76100
def broadcast_callback(payload):
77-
print("broadcast: ", payload)
78101
received_events.append(payload)
79102
semaphore.release()
80103

@@ -111,41 +134,50 @@ async def test_postgrest_changes(socket: AsyncRealtimeClient):
111134
await socket.set_auth(token)
112135

113136
channel: AsyncRealtimeChannel = socket.channel("test-postgres-changes")
114-
received_events = {"all": [], "insert": [], "update": [], "delete": []}
137+
received_events: dict[str, list[dict]] = {
138+
"all": [],
139+
"insert": [],
140+
"update": [],
141+
"delete": [],
142+
}
115143

116144
def all_changes_callback(payload):
117-
print("all_changes_callback: ", payload)
118145
received_events["all"].append(payload)
119146

120147
insert_event = asyncio.Event()
121148

122149
def insert_callback(payload):
123-
print("insert_callback: ", payload)
124150
received_events["insert"].append(payload)
125151
insert_event.set()
126152

127153
update_event = asyncio.Event()
128154

129155
def update_callback(payload):
130-
print("update_callback: ", payload)
131156
received_events["update"].append(payload)
132157
update_event.set()
133158

134159
delete_event = asyncio.Event()
135160

136161
def delete_callback(payload):
137-
print("delete_callback: ", payload)
138162
received_events["delete"].append(payload)
139163
delete_event.set()
140164

141165
subscribed_event = asyncio.Event()
142166
system_event = asyncio.Event()
143167

144168
await (
145-
channel.on_postgres_changes("*", all_changes_callback, table="todos")
146-
.on_postgres_changes("INSERT", insert_callback, table="todos")
147-
.on_postgres_changes("UPDATE", update_callback, table="todos")
148-
.on_postgres_changes("DELETE", delete_callback, table="todos")
169+
channel.on_postgres_changes(
170+
RealtimePostgresChangesListenEvent.All, all_changes_callback, table="todos"
171+
)
172+
.on_postgres_changes(
173+
RealtimePostgresChangesListenEvent.Insert, insert_callback, table="todos"
174+
)
175+
.on_postgres_changes(
176+
RealtimePostgresChangesListenEvent.Update, update_callback, table="todos"
177+
)
178+
.on_postgres_changes(
179+
RealtimePostgresChangesListenEvent.Delete, delete_callback, table="todos"
180+
)
149181
.on_system(lambda _: system_event.set())
150182
.subscribe(
151183
lambda state, _: (
@@ -206,26 +238,30 @@ async def test_postgrest_changes_on_different_tables(socket: AsyncRealtimeClient
206238
await socket.set_auth(token)
207239

208240
channel: AsyncRealtimeChannel = socket.channel("test-postgres-changes")
209-
received_events = {"all": [], "insert": []}
241+
received_events: dict[str, list[dict]] = {"all": [], "insert": []}
210242

211243
def all_changes_callback(payload):
212-
print("all_changes_callback: ", payload)
213244
received_events["all"].append(payload)
214245

215246
insert_event = asyncio.Event()
216247

217248
def insert_callback(payload):
218-
print("insert_callback: ", payload)
219249
received_events["insert"].append(payload)
220250
insert_event.set()
221251

222252
subscribed_event = asyncio.Event()
223253
system_event = asyncio.Event()
224254

225255
await (
226-
channel.on_postgres_changes("*", all_changes_callback, table="todos")
227-
.on_postgres_changes("INSERT", insert_callback, table="todos")
228-
.on_postgres_changes("INSERT", insert_callback, table="messages")
256+
channel.on_postgres_changes(
257+
RealtimePostgresChangesListenEvent.All, all_changes_callback, table="todos"
258+
)
259+
.on_postgres_changes(
260+
RealtimePostgresChangesListenEvent.Insert, insert_callback, table="todos"
261+
)
262+
.on_postgres_changes(
263+
RealtimePostgresChangesListenEvent.Insert, insert_callback, table="messages"
264+
)
229265
.on_system(lambda _: system_event.set())
230266
.subscribe(
231267
lambda state, _: (
@@ -273,6 +309,10 @@ def insert_callback(payload):
273309
await socket.close()
274310

275311

312+
class CreateTodoResponse(BaseModel):
313+
id: str
314+
315+
276316
async def create_todo(access_token: str, todo: dict) -> str:
277317
url = f"{URL}/rest/v1/todos?select=id"
278318
headers = {
@@ -286,8 +326,11 @@ async def create_todo(access_token: str, todo: dict) -> str:
286326
async with aiohttp.ClientSession() as session:
287327
async with session.post(url, headers=headers, json=todo) as response:
288328
if response.status == 201:
289-
json_response = await response.json()
290-
return json_response.get("id")
329+
response_content = await response.read()
330+
create_todo_response = CreateTodoResponse.model_validate_json(
331+
response_content
332+
)
333+
return create_todo_response.id
291334
else:
292335
raise Exception(f"Failed to create todo. Status: {response.status}")
293336

@@ -306,7 +349,11 @@ async def update_todo(access_token: str, id: str, todo: dict):
306349
raise Exception(f"Failed to update todo. Status: {response.status}")
307350

308351

309-
async def create_message(access_token: str, message: dict) -> str:
352+
class CreateMsgResponse(BaseModel):
353+
id: int
354+
355+
356+
async def create_message(access_token: str, message: dict) -> int:
310357
url = f"{URL}/rest/v1/messages?select=id"
311358
headers = {
312359
"apikey": ANON_KEY,
@@ -319,8 +366,11 @@ async def create_message(access_token: str, message: dict) -> str:
319366
async with aiohttp.ClientSession() as session:
320367
async with session.post(url, headers=headers, json=message) as response:
321368
if response.status == 201:
322-
json_response = await response.json()
323-
return json_response.get("id")
369+
response_content = await response.read()
370+
create_msg_response = CreateMsgResponse.model_validate_json(
371+
response_content
372+
)
373+
return create_msg_response.id
324374
else:
325375
raise Exception(f"Failed to create message. Status: {response.status}")
326376

0 commit comments

Comments
 (0)