Skip to content

Commit 56e8a5f

Browse files
add unread_count and unread_count_batch prep (#153)
* add unread_count and unread_count_batch prep * lint-fix * add await * await and str(uuid) * lint-fix * fix deprecation warnings * upsert_user_partial -> update_user_partial * require 0.21.1 of pytest-asyncio https://pytest-asyncio.readthedocs.io/en/latest/reference/changelog.html\#known-issues * drop support for 3.7, add support for 3.11 and 3.12 (#154) * enable tests for batch unread endpoint * fix: add tests for unread threads * fix: lint
1 parent 8e59e11 commit 56e8a5f

File tree

11 files changed

+165
-22
lines changed

11 files changed

+165
-22
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ jobs:
1717
fail-fast: false
1818
max-parallel: 1
1919
matrix:
20-
python: ["3.7", "3.8", "3.9", "3.10"]
20+
python: ["3.8", "3.9", "3.10", "3.11", "3.12"]
2121
steps:
2222
- name: Checkout
2323
uses: actions/checkout@v3
2424
with:
2525
fetch-depth: 0 # gives the commit message linter access to all previous commits
2626

2727
- name: Commit lint
28-
if: ${{ matrix.python == '3.7' && github.ref == 'refs/heads/master' }}
28+
if: ${{ matrix.python == '3.8' && github.ref == 'refs/heads/master' }}
2929
uses: wagoid/commitlint-github-action@v4
3030

3131
- uses: actions/setup-python@v3
@@ -36,7 +36,7 @@ jobs:
3636
run: pip install ".[test, ci]"
3737

3838
- name: Lint with ${{ matrix.python }}
39-
if: ${{ matrix.python == '3.7' }}
39+
if: ${{ matrix.python == '3.8' }}
4040
run: make lint
4141

4242
- name: Test with ${{ matrix.python }}

setup.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"pyjwt>=2.0.0,<3",
99
"typing_extensions; python_version < '3.8'",
1010
]
11-
tests_require = ["pytest", "pytest-asyncio"]
11+
tests_require = ["pytest", "pytest-asyncio <= 0.21.1"]
1212
ci_require = [
1313
"black",
1414
"flake8",
@@ -48,7 +48,7 @@
4848
install_requires=install_requires,
4949
extras_require={"test": tests_require, "ci": ci_require},
5050
include_package_data=True,
51-
python_requires=">=3.7",
51+
python_requires=">=3.8",
5252
classifiers=[
5353
"Intended Audience :: Developers",
5454
"Intended Audience :: System Administrators",
@@ -57,10 +57,11 @@
5757
"Development Status :: 5 - Production/Stable",
5858
"Natural Language :: English",
5959
"Programming Language :: Python :: 3",
60-
"Programming Language :: Python :: 3.7",
6160
"Programming Language :: Python :: 3.8",
6261
"Programming Language :: Python :: 3.9",
6362
"Programming Language :: Python :: 3.10",
63+
"Programming Language :: Python :: 3.11",
64+
"Programming Language :: Python :: 3.12",
6465
"Topic :: Software Development :: Libraries :: Python Modules",
6566
],
6667
)

stream_chat/async_chat/client.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,12 @@ async def get_import(self, id: str) -> StreamResponse:
791791
async def list_imports(self, options: Dict = None) -> StreamResponse:
792792
return await self.get("imports", params=options)
793793

794+
async def unread_counts(self, user_id: str) -> StreamResponse:
795+
return await self.get("unread", params={"user_id": user_id})
796+
797+
async def unread_counts_batch(self, user_ids: List[str]) -> StreamResponse:
798+
return await self.post("unread_batch", data={"user_ids": user_ids})
799+
794800
async def close(self) -> None:
795801
await self.session.close()
796802

stream_chat/base/client.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1318,6 +1318,24 @@ def list_imports(
13181318
"""
13191319
pass
13201320

1321+
@abc.abstractmethod
1322+
def unread_counts(
1323+
self, user_id: str
1324+
) -> Union[StreamResponse, Awaitable[StreamResponse]]:
1325+
"""
1326+
Get unread counts for a single user.
1327+
"""
1328+
pass
1329+
1330+
@abc.abstractmethod
1331+
def unread_counts_batch(
1332+
self, user_ids: List[str]
1333+
) -> Union[StreamResponse, Awaitable[StreamResponse]]:
1334+
"""
1335+
Get unread counts for multiple users at once.
1336+
"""
1337+
pass
1338+
13211339
#####################
13221340
# Private methods #
13231341
#####################

stream_chat/client.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -753,3 +753,9 @@ def get_import(self, id: str) -> StreamResponse:
753753

754754
def list_imports(self, options: Dict = None) -> StreamResponse:
755755
return self.get("imports", params=options)
756+
757+
def unread_counts(self, user_id: str) -> StreamResponse:
758+
return self.get("unread", params={"user_id": user_id})
759+
760+
def unread_counts_batch(self, user_ids: List[str]) -> StreamResponse:
761+
return self.post("unread_batch", data={"user_ids": user_ids})

stream_chat/tests/async_chat/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ async def client():
5050
@pytest.fixture(scope="function")
5151
async def random_user(client: StreamChatAsync):
5252
user = {"id": str(uuid.uuid4())}
53-
response = await client.update_user(user)
53+
response = await client.upsert_user(user)
5454
assert "users" in response
5555
assert user["id"] in response["users"]
5656
yield user
@@ -60,7 +60,7 @@ async def random_user(client: StreamChatAsync):
6060
@pytest.fixture(scope="function")
6161
async def server_user(client: StreamChatAsync):
6262
user = {"id": str(uuid.uuid4())}
63-
response = await client.update_user(user)
63+
response = await client.upsert_user(user)
6464
assert "users" in response
6565
assert user["id"] in response["users"]
6666
yield user

stream_chat/tests/async_chat/test_channel.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ async def test_channel_hide_show(
276276

277277
async def test_invites(self, client: StreamChatAsync, channel: Channel):
278278
members = ["john", "paul", "george", "pete", "ringo", "eric"]
279-
await client.update_users([{"id": m} for m in members])
279+
await client.upsert_users([{"id": m} for m in members])
280280
channel = client.channel(
281281
"team",
282282
"beatles-" + str(uuid.uuid4()),
@@ -305,7 +305,7 @@ async def test_invites(self, client: StreamChatAsync, channel: Channel):
305305

306306
async def test_query_members(self, client: StreamChatAsync, channel: Channel):
307307
members = ["paul", "george", "john", "jessica", "john2"]
308-
await client.update_users([{"id": m, "name": m} for m in members])
308+
await client.upsert_users([{"id": m, "name": m} for m in members])
309309
for member in members:
310310
await channel.add_members([member])
311311

stream_chat/tests/async_chat/test_client.py

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ async def test_get_app_settings(self, client: StreamChatAsync):
136136

137137
async def test_update_user(self, client: StreamChatAsync):
138138
user = {"id": str(uuid.uuid4())}
139-
response = await client.update_user(user)
139+
response = await client.upsert_user(user)
140140
assert "users" in response
141141
assert user["id"] in response["users"]
142142

@@ -148,7 +148,7 @@ async def test_update_users(self, client: StreamChatAsync):
148148

149149
async def test_update_user_partial(self, client: StreamChatAsync):
150150
user_id = str(uuid.uuid4())
151-
await client.update_user({"id": user_id, "field": "value"})
151+
await client.upsert_user({"id": user_id, "field": "value"})
152152

153153
response = await client.update_user_partial(
154154
{"id": user_id, "set": {"field": "updated"}}
@@ -785,7 +785,7 @@ async def test_imports_end2end(self, client: StreamChatAsync):
785785
headers={"Content-Type": "application/json"},
786786
) as resp:
787787
assert resp.status == 200
788-
sess.close()
788+
await sess.close()
789789

790790
create_resp = await client.create_import(url_resp["path"], "upsert")
791791
assert create_resp["import_task"]["id"]
@@ -795,3 +795,64 @@ async def test_imports_end2end(self, client: StreamChatAsync):
795795

796796
list_resp = await client.list_imports({"limit": 1})
797797
assert len(list_resp["import_tasks"]) == 1
798+
799+
async def test_unread_counts(
800+
self, client: StreamChatAsync, channel, random_user: Dict
801+
):
802+
await channel.add_members([random_user["id"]])
803+
msg_id = str(uuid.uuid4())
804+
await channel.send_message(
805+
{"id": msg_id, "text": "helloworld"}, str(uuid.uuid4())
806+
)
807+
response = await client.unread_counts(random_user["id"])
808+
assert "total_unread_count" in response
809+
assert "channels" in response
810+
assert "channel_type" in response
811+
assert response["total_unread_count"] == 1
812+
assert len(response["channels"]) == 1
813+
assert response["channels"][0]["channel_id"] == channel.cid
814+
assert len(response["channel_type"]) == 1
815+
816+
# test threads unread counts
817+
await channel.send_message(
818+
{"parent_id": msg_id, "text": "helloworld"}, random_user["id"]
819+
)
820+
await channel.send_message(
821+
{"parent_id": msg_id, "text": "helloworld"}, str(uuid.uuid4())
822+
)
823+
response = await client.unread_counts(random_user["id"])
824+
assert "total_unread_threads_count" in response
825+
assert "threads" in response
826+
assert response["total_unread_threads_count"] == 1
827+
assert len(response["threads"]) == 1
828+
assert response["threads"][0]["parent_message_id"] == msg_id
829+
830+
async def test_unread_counts_batch(
831+
self, client: StreamChatAsync, channel, random_users: Dict
832+
):
833+
await channel.add_members([x["id"] for x in random_users])
834+
msg_id = str(uuid.uuid4())
835+
await channel.send_message(
836+
{"id": msg_id, "text": "helloworld"}, str(uuid.uuid4())
837+
)
838+
response = await client.unread_counts_batch([x["id"] for x in random_users])
839+
assert "counts_by_user" in response
840+
for user_id in [x["id"] for x in random_users]:
841+
assert user_id in response["counts_by_user"]
842+
assert response["counts_by_user"][user_id]["total_unread_count"] == 1
843+
844+
# send this message to add user to the thread
845+
await channel.send_message(
846+
{"parent_id": msg_id, "text": "helloworld"}, user_id
847+
)
848+
849+
# test threads unread counts
850+
await channel.send_message(
851+
{"parent_id": msg_id, "text": "helloworld"}, str(uuid.uuid4())
852+
)
853+
response = await client.unread_counts_batch([x["id"] for x in random_users])
854+
for user_id in [x["id"] for x in random_users]:
855+
assert user_id in response["counts_by_user"]
856+
assert (
857+
response["counts_by_user"][user_id]["total_unread_threads_count"] == 1
858+
)

stream_chat/tests/conftest.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def client():
4040
@pytest.fixture(scope="function")
4141
def random_user(client: StreamChat):
4242
user = {"id": str(uuid.uuid4())}
43-
response = client.update_user(user)
43+
response = client.upsert_user(user)
4444
assert "users" in response
4545
assert user["id"] in response["users"]
4646
yield user
@@ -50,7 +50,7 @@ def random_user(client: StreamChat):
5050
@pytest.fixture(scope="function")
5151
def server_user(client: StreamChat):
5252
user = {"id": str(uuid.uuid4())}
53-
response = client.update_user(user)
53+
response = client.upsert_user(user)
5454
assert "users" in response
5555
assert user["id"] in response["users"]
5656
yield user
@@ -62,7 +62,7 @@ def random_users(client: StreamChat):
6262
user1 = {"id": str(uuid.uuid4())}
6363
user2 = {"id": str(uuid.uuid4())}
6464
user3 = {"id": str(uuid.uuid4())}
65-
client.update_users([user1, user2, user3])
65+
client.upsert_users([user1, user2, user3])
6666
yield [user1, user2, user3]
6767
hard_delete_users(client, [user1["id"], user2["id"], user3["id"]])
6868

@@ -111,7 +111,7 @@ def fellowship_of_the_ring(client: StreamChat):
111111
},
112112
{"id": "peregrin-took", "name": "Peregrin Took", "race": "Hobbit", "age": 28},
113113
]
114-
client.update_users(members)
114+
client.upsert_users(members)
115115
channel = client.channel(
116116
"team", "fellowship-of-the-ring", {"members": [m["id"] for m in members]}
117117
)

stream_chat/tests/test_channel.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ def test_channel_hide_show(
276276

277277
def test_invites(self, client: StreamChat, channel: Channel):
278278
members = ["john", "paul", "george", "pete", "ringo", "eric"]
279-
client.update_users([{"id": m} for m in members])
279+
client.upsert_users([{"id": m} for m in members])
280280
channel = client.channel(
281281
"team",
282282
"beatles-" + str(uuid.uuid4()),
@@ -305,7 +305,7 @@ def test_invites(self, client: StreamChat, channel: Channel):
305305

306306
def test_query_members(self, client: StreamChat, channel: Channel):
307307
members = ["paul", "george", "john", "jessica", "john2"]
308-
client.update_users([{"id": m, "name": m} for m in members])
308+
client.upsert_users([{"id": m, "name": m} for m in members])
309309
for member in members:
310310
channel.add_members([member])
311311

0 commit comments

Comments
 (0)