Skip to content
Merged
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
26 changes: 26 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# This workflow will install Python dependencies and run linting
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Test

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
lint:
runs-on: ubuntu-latest

steps:
- name: Check out code from GitHub
uses: actions/checkout@v6.0.1
- name: Install uv
uses: astral-sh/setup-uv@v6
- name: Set up Python
run: uv python install 3.12
- name: Install dependencies
run: uv sync --extra test
- name: Lint/test with pre-commit
run: SKIP=no-commit-to-branch uv run pre-commit run --all-files
4 changes: 3 additions & 1 deletion sendspin/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,9 @@ async def _process_service_info(
self._first_result.set_result(url)

def _schedule(self, zeroconf: AsyncZeroconf, service_type: str, name: str) -> None:
task = create_task(self._process_service_info(zeroconf, service_type, name), loop=self._loop)
task = create_task(
self._process_service_info(zeroconf, service_type, name), loop=self._loop
)
self.tasks.add(task)
task.add_done_callback(self.tasks.discard)
task.add_done_callback(lambda t: t.exception() if not t.cancelled() else None)
Expand Down
17 changes: 7 additions & 10 deletions sendspin/serve/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def get_local_ip() -> str:
try:
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
s.connect(("8.8.8.8", 80))
return s.getsockname()[0]
ip: str = s.getsockname()[0]
return ip
except Exception:
return "localhost"

Expand All @@ -59,7 +60,7 @@ class ServeConfig:
name: str = "Sendspin Server"


def _windows_exception_handler(loop: asyncio.AbstractEventLoop, context: dict) -> None:
def _windows_exception_handler(loop: asyncio.AbstractEventLoop, context: dict[str, object]) -> None:
"""Suppress ConnectionResetError on Windows during socket shutdown.

On Windows, the ProactorEventLoop raises ConnectionResetError (WinError 10054)
Expand Down Expand Up @@ -93,7 +94,7 @@ async def run_server(config: ServeConfig) -> int:

client_connected = asyncio.Event()
active_group: SendspinGroup | None = None
play_media_task: asyncio.Task[None] | None = None
play_media_task: asyncio.Task[int] | None = None
shutdown_requested = False

def handle_sigint() -> None:
Expand Down Expand Up @@ -175,13 +176,10 @@ async def on_server_event(server: SendspinServer, event: SendspinEvent) -> None:
# Wait for a client to connect
if not active_group:
client_connected.clear()
try:
await client_connected.wait()
except asyncio.CancelledError:
raise
await client_connected.wait()

if shutdown_requested:
break
break # type: ignore[unreachable]

assert active_group is not None

Expand All @@ -195,8 +193,7 @@ async def on_server_event(server: SendspinServer, event: SendspinEvent) -> None:
play_media_task = create_task(active_group.play_media(media_stream))
await play_media_task
except asyncio.CancelledError:
if shutdown_requested:
break
pass
except Exception as e:
print(f"Playback error: {e}")
logger.debug("Playback error", exc_info=True)
Expand Down
1 change: 0 additions & 1 deletion sendspin/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
from __future__ import annotations

import asyncio
import inspect
import sys
from collections.abc import Coroutine
from typing import TypeVar
Expand Down