Skip to content
Open
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions livekit-rtc/livekit/rtc/participant.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,18 @@
import os
import mimetypes
import weakref
from typing import List, Union, Callable, Dict, Awaitable, Optional, Mapping, cast, TypeVar
from typing import (
List,
Union,
Callable,
Dict,
Awaitable,
Optional,
Mapping,
cast,
TypeVar,
Sequence,
)
from abc import abstractmethod, ABC

from ._ffi_client import FfiClient, FfiHandle
Expand Down Expand Up @@ -317,7 +328,7 @@ async def publish_data(
payload: Union[bytes, str],
*,
reliable: bool = True,
destination_identities: List[str] = [],
destination_identities: Optional[Sequence[str]] = None,
topic: str = "",
) -> None:
"""
Expand All @@ -326,7 +337,7 @@ async def publish_data(
Args:
payload (Union[bytes, str]): The data to publish.
reliable (bool, optional): Whether to send reliably or not. Defaults to True.
destination_identities (List[str], optional): List of participant identities to send to. Defaults to [].
destination_identities (Optional[Sequence[str]], optional): Sequence of participant identities to send to. Defaults to None.
topic (str, optional): The topic under which to publish the data. Defaults to "".

Raises:
Expand All @@ -344,7 +355,8 @@ async def publish_data(
req.publish_data.data_len = data_len
req.publish_data.reliable = reliable
req.publish_data.topic = topic
req.publish_data.destination_identities.extend(destination_identities)
if destination_identities:
req.publish_data.destination_identities.extend(destination_identities)

queue = FfiClient.instance.queue.subscribe()
try:
Expand Down
76 changes: 76 additions & 0 deletions tests/rtc/test_participant_publish_data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from __future__ import annotations

import inspect
import os
import pytest

from livekit import rtc
from livekit.rtc import _ffi_client
from livekit.rtc.participant import LocalParticipant
from livekit.rtc._proto import ffi_pb2 as proto_ffi
from livekit.rtc._proto import handle_pb2 as proto_handle
from livekit.rtc._proto import participant_pb2 as proto_participant


def _create_local_participant() -> LocalParticipant:
room = rtc.Room()
return LocalParticipant(
room._room_queue,
proto_participant.OwnedParticipant(
handle=proto_handle.FfiOwnedHandle(id=0),
info=proto_participant.ParticipantInfo(
sid="PA_TEST",
identity="tester",
),
),
)


def test_publish_data_parameter_default_is_none() -> None:
sig = inspect.signature(LocalParticipant.publish_data)
param = sig.parameters["destination_identities"]
assert param.default is None


@pytest.mark.asyncio
async def test_publish_data_accepts_none_and_sequences(monkeypatch: pytest.MonkeyPatch) -> None:
lp = _create_local_participant()
captured_requests: list[proto_ffi.FfiRequest] = []

class _MockFfiClient:
def __init__(self) -> None:
self.queue: _ffi_client.FfiQueue[proto_ffi.FfiEvent] = _ffi_client.FfiQueue()
self._pid = os.getpid()

def request(self, req: proto_ffi.FfiRequest) -> proto_ffi.FfiResponse:
captured_requests.append(req)
resp = proto_ffi.FfiResponse()
resp.publish_data.async_id = 42

ev = proto_ffi.FfiEvent()
ev.publish_data.async_id = 42
self.queue.put(ev)
return resp

mock_client = _MockFfiClient()
monkeypatch.setattr(_ffi_client.FfiClient, "_instance", mock_client)

# 1. Default (omitted)
await lp.publish_data(b"msg1")
assert list(captured_requests[-1].publish_data.destination_identities) == []

# 2. Explicit None
await lp.publish_data(b"msg2", destination_identities=None)
assert list(captured_requests[-1].publish_data.destination_identities) == []

# 3. Explicit empty list
await lp.publish_data(b"msg3", destination_identities=[])
assert list(captured_requests[-1].publish_data.destination_identities) == []

# 4. List of identities
await lp.publish_data(b"msg4", destination_identities=["user1", "user2"])
assert list(captured_requests[-1].publish_data.destination_identities) == ["user1", "user2"]

# 5. Tuple of identities
await lp.publish_data(b"msg5", destination_identities=("user3", "user4"))
assert list(captured_requests[-1].publish_data.destination_identities) == ["user3", "user4"]
Loading