Skip to content

Commit d766ae5

Browse files
committed
Address review: take viewing user id, use unpack_thread_id
- thread_to_pb / total_num_responses now take viewing_user_id instead of the full CouchersContext; callers pass context.user_id. - approve_thread_post uses unpack_thread_id rather than duplicating the divmod-by-10 convention; moved the depth convention to pack_thread_id's docstring.
1 parent 9d2de66 commit d766ae5

6 files changed

Lines changed: 29 additions & 26 deletions

File tree

app/backend/src/couchers/servicers/discussions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def discussion_to_pb(session: Session, discussion: Discussion, context: Couchers
4141
owner_title=discussion.owner_cluster.name,
4242
title=discussion.title,
4343
content=discussion.content,
44-
thread=thread_to_pb(session, context, discussion.thread_id),
44+
thread=thread_to_pb(session, context.user_id, discussion.thread_id),
4545
can_moderate=can_moderate,
4646
)
4747

app/backend/src/couchers/servicers/events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ def event_to_pb(session: Session, occurrence: EventOccurrence, context: Couchers
204204
owner_user_id=event.owner_user_id,
205205
owner_community_id=owner_community_id,
206206
owner_group_id=owner_group_id,
207-
thread=thread_to_pb(session, context, event.thread_id),
207+
thread=thread_to_pb(session, context.user_id, event.thread_id),
208208
can_edit=can_edit,
209209
can_moderate=can_moderate,
210210
)

app/backend/src/couchers/servicers/pages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def page_to_pb(session: Session, page: Page, context: CouchersContext) -> pages_
7878
owner_user_id=page.owner_user_id,
7979
owner_community_id=owner_community_id,
8080
owner_group_id=owner_group_id,
81-
thread=thread_to_pb(session, context, page.thread_id),
81+
thread=thread_to_pb(session, context.user_id, page.thread_id),
8282
title=current_version.title,
8383
content=current_version.content,
8484
photo_url=current_version.photo.full_url if current_version.photo_key else None,

app/backend/src/couchers/servicers/threads.py

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
from sqlalchemy.orm import Session
77
from sqlalchemy.sql import func
88

9-
from couchers.context import CouchersContext, make_background_user_context
9+
from couchers.context import CouchersContext, make_background_user_context, make_logged_out_context
1010
from couchers.db import session_scope
11+
from couchers.i18n import LocalizationContext
1112
from couchers.jobs.enqueue import queue_job
1213
from couchers.models import (
1314
Comment,
@@ -31,21 +32,30 @@
3132

3233
logger = logging.getLogger(__name__)
3334

34-
# Since the API exposes a single ID space regardless of nesting level,
35-
# we construct the API id by appending the nesting level to the
36-
# database ID.
37-
3835

3936
def pack_thread_id(database_id: int, depth: int) -> int:
37+
"""Pack (database_id, depth) into a single API thread id.
38+
39+
The API exposes a single ID space regardless of nesting level, so we append
40+
the nesting level (depth) as the trailing digit of the database id: depth 0
41+
= Thread, depth 1 = Comment, depth 2 = Reply.
42+
"""
4043
return database_id * 10 + depth
4144

4245

4346
def unpack_thread_id(thread_id: int) -> tuple[int, int]:
44-
"""Returns (database_id, depth) tuple."""
47+
"""Inverse of pack_thread_id; returns (database_id, depth)."""
4548
return divmod(thread_id, 10)
4649

4750

48-
def total_num_responses(session: Session, context: CouchersContext, database_id: int) -> int:
51+
def _viewing_context(viewing_user_id: int | None) -> CouchersContext:
52+
if viewing_user_id is not None:
53+
return make_background_user_context(user_id=viewing_user_id)
54+
return make_logged_out_context(LocalizationContext.en_utc())
55+
56+
57+
def total_num_responses(session: Session, viewing_user_id: int | None, database_id: int) -> int:
58+
context = _viewing_context(viewing_user_id)
4959
comments = where_moderated_content_visible(
5060
select(func.count()).select_from(Comment).where(Comment.thread_id == database_id),
5161
context,
@@ -64,10 +74,10 @@ def total_num_responses(session: Session, context: CouchersContext, database_id:
6474
return session.execute(comments).scalar_one() + session.execute(replies).scalar_one()
6575

6676

67-
def thread_to_pb(session: Session, context: CouchersContext, database_id: int) -> threads_pb2.Thread:
77+
def thread_to_pb(session: Session, viewing_user_id: int | None, database_id: int) -> threads_pb2.Thread:
6878
return threads_pb2.Thread(
6979
thread_id=pack_thread_id(database_id, 0),
70-
num_responses=total_num_responses(session, context, database_id),
80+
num_responses=total_num_responses(session, viewing_user_id, database_id),
7181
)
7282

7383

app/backend/src/tests/fixtures/misc.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from couchers.notifications.push import PushNotificationContent
1212
from couchers.proto import moderation_pb2
1313
from couchers.proto.internal import jobs_pb2
14+
from couchers.servicers.threads import unpack_thread_id
1415
from tests.fixtures.sessions import real_moderation_session
1516

1617

@@ -212,12 +213,8 @@ def approve_reply(self, reply_id: int, reason: str = "Test approval") -> None:
212213
)
213214

214215
def approve_thread_post(self, packed_thread_id: int, reason: str = "Test approval") -> None:
215-
"""Approve whichever of Comment/Reply the packed thread_id refers to.
216-
217-
packed_thread_id uses the convention from couchers.servicers.threads.pack_thread_id:
218-
the trailing digit is depth (1=Comment, 2=Reply); the rest is the database id.
219-
"""
220-
database_id, depth = divmod(packed_thread_id, 10)
216+
"""Approve whichever of Comment/Reply the packed thread_id refers to."""
217+
database_id, depth = unpack_thread_id(packed_thread_id)
221218
if depth == 1:
222219
self.approve_comment(database_id, reason=reason)
223220
elif depth == 2:

app/backend/src/tests/test_threads.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -338,18 +338,16 @@ def test_admin_can_hide_comment(db):
338338

339339

340340
def test_total_num_responses_excludes_shadowed(db):
341-
from couchers.context import make_background_user_context # noqa: PLC0415
342341
from couchers.servicers.threads import total_num_responses # noqa: PLC0415
343342

344343
author, author_token = generate_user()
345344
viewer, _ = generate_user()
346345
parent_thread_id, _ = _make_thread_and_comment(author_token, content="one")
347-
viewer_context = make_background_user_context(user_id=viewer.id)
348346

349347
parent_db_id, _ = divmod(parent_thread_id, 10)
350348

351349
with session_scope() as session:
352-
assert total_num_responses(session, viewer_context, parent_db_id) == 0
350+
assert total_num_responses(session, viewer.id, parent_db_id) == 0
353351

354352
with session_scope() as session:
355353
state = session.execute(
@@ -361,20 +359,18 @@ def test_total_num_responses_excludes_shadowed(db):
361359
state.visibility = ModerationVisibility.visible
362360

363361
with session_scope() as session:
364-
assert total_num_responses(session, viewer_context, parent_db_id) == 1
362+
assert total_num_responses(session, viewer.id, parent_db_id) == 1
365363

366364

367365
def test_total_num_responses_includes_own_shadowed(db):
368-
"""The count uses the viewer's context so authors see their own shadowed content in the total,
366+
"""The count uses the viewer's id so authors see their own shadowed content in the total,
369367
matching what GetThread shows them in the list."""
370-
from couchers.context import make_background_user_context # noqa: PLC0415
371368
from couchers.servicers.threads import total_num_responses # noqa: PLC0415
372369

373370
author, author_token = generate_user()
374371
parent_thread_id, _ = _make_thread_and_comment(author_token, content="one")
375-
author_context = make_background_user_context(user_id=author.id)
376372

377373
parent_db_id, _ = divmod(parent_thread_id, 10)
378374

379375
with session_scope() as session:
380-
assert total_num_responses(session, author_context, parent_db_id) == 1
376+
assert total_num_responses(session, author.id, parent_db_id) == 1

0 commit comments

Comments
 (0)