fix: rename src/websocket to src/ws_manager to avoid websocket-client clash
selenium depends on websocket-client which installs a top-level `websocket` package that shadows our src/websocket/ module on CI. Renaming to ws_manager eliminates the conflict entirely — no more sys.path hacks needed in conftest or Selenium tests. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -41,7 +41,7 @@ src/
|
||||
lightning/ # Lightning backend abstraction (mock + LND)
|
||||
agent_core/ # Substrate-agnostic agent interface
|
||||
voice/ # NLU intent detection (regex-based, no cloud)
|
||||
websocket/ # WebSocket manager (ws_manager singleton)
|
||||
ws_manager/ # WebSocket manager (ws_manager singleton)
|
||||
notifications/ # Push notification store (notifier singleton)
|
||||
shortcuts/ # Siri Shortcuts API endpoints
|
||||
telegram_bot/ # Telegram bridge
|
||||
@@ -256,7 +256,7 @@ runner.stop(info["container_id"])
|
||||
```python
|
||||
from dashboard.store import message_log
|
||||
from notifications.push import notifier
|
||||
from websocket.handler import ws_manager
|
||||
from ws_manager.handler import ws_manager
|
||||
from timmy_serve.payment_handler import payment_handler
|
||||
from swarm.coordinator import coordinator
|
||||
```
|
||||
|
||||
@@ -63,7 +63,7 @@ src/
|
||||
lightning/ # Lightning backend abstraction (mock + LND)
|
||||
agent_core/ # Substrate-agnostic agent interface
|
||||
voice/ # NLU intent detection (regex-based, local)
|
||||
websocket/ # WebSocket connection manager (ws_manager singleton)
|
||||
ws_manager/ # WebSocket connection manager (ws_manager singleton)
|
||||
notifications/ # Push notification store (notifier singleton)
|
||||
shortcuts/ # Siri Shortcuts API endpoints
|
||||
telegram_bot/ # Telegram bridge
|
||||
@@ -96,7 +96,7 @@ Core services are module-level singleton instances imported directly:
|
||||
```python
|
||||
from dashboard.store import message_log
|
||||
from notifications.push import notifier
|
||||
from websocket.handler import ws_manager
|
||||
from ws_manager.handler import ws_manager
|
||||
from timmy_serve.payment_handler import payment_handler
|
||||
from swarm.coordinator import coordinator
|
||||
```
|
||||
|
||||
@@ -212,7 +212,7 @@ src/
|
||||
lightning/ # Lightning backend abstraction (mock + LND)
|
||||
agent_core/ # Substrate-agnostic agent interface
|
||||
voice/ # NLU intent detection
|
||||
websocket/ # WebSocket connection manager
|
||||
ws_manager/ # WebSocket connection manager
|
||||
notifications/ # Push notification store
|
||||
shortcuts/ # Siri Shortcuts endpoints
|
||||
telegram_bot/ # Telegram bridge
|
||||
|
||||
@@ -86,7 +86,7 @@ include = [
|
||||
"src/config.py",
|
||||
"src/self_tdd",
|
||||
"src/swarm",
|
||||
"src/websocket",
|
||||
"src/ws_manager",
|
||||
"src/voice",
|
||||
"src/notifications",
|
||||
"src/shortcuts",
|
||||
|
||||
@@ -9,7 +9,7 @@ import logging
|
||||
|
||||
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
|
||||
|
||||
from websocket.handler import ws_manager
|
||||
from ws_manager.handler import ws_manager
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -6,15 +6,6 @@ import sys
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
# ── Fix websocket-client shadowing project's src/websocket/ ──────────────────
|
||||
# selenium → websocket-client installs a top-level `websocket` package that
|
||||
# shadows our src/websocket/ module. Ensure src/ is at the FRONT of sys.path
|
||||
# so our module wins the import race.
|
||||
_src = str(Path(__file__).resolve().parent.parent / "src")
|
||||
if _src in sys.path:
|
||||
sys.path.remove(_src)
|
||||
sys.path.insert(0, _src)
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
|
||||
@@ -6,14 +6,19 @@ Requires:
|
||||
- selenium pip package
|
||||
|
||||
Run:
|
||||
SELENIUM_UI=1 pytest tests/functional/test_ui_selenium.py -v --override-ini='pythonpath='
|
||||
SELENIUM_UI=1 pytest tests/functional/test_ui_selenium.py -v
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
import pytest
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.options import Options
|
||||
from selenium.webdriver.common.by import By
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
from selenium.webdriver.support.ui import WebDriverWait
|
||||
|
||||
# Skip entire module unless SELENIUM_UI=1 is set
|
||||
pytestmark = pytest.mark.skipif(
|
||||
@@ -24,27 +29,6 @@ pytestmark = pytest.mark.skipif(
|
||||
DASHBOARD_URL = os.environ.get("DASHBOARD_URL", "http://localhost:8000")
|
||||
|
||||
|
||||
# ── Prevent src/websocket from shadowing the websocket-client package ────────
|
||||
# Selenium depends on websocket-client which provides `from websocket import
|
||||
# WebSocketApp`. The project's src/websocket/ module would shadow that import.
|
||||
# Remove "src" from sys.path for this module since we don't import project code.
|
||||
_src_paths = [p for p in sys.path if p.endswith("/src") or p.endswith("\\src")]
|
||||
for _p in _src_paths:
|
||||
sys.path.remove(_p)
|
||||
|
||||
from selenium import webdriver # noqa: E402
|
||||
from selenium.webdriver.chrome.options import Options # noqa: E402
|
||||
from selenium.webdriver.common.by import By # noqa: E402
|
||||
from selenium.webdriver.common.keys import Keys # noqa: E402
|
||||
from selenium.webdriver.support import expected_conditions as EC # noqa: E402
|
||||
from selenium.webdriver.support.ui import WebDriverWait # noqa: E402
|
||||
|
||||
# Restore paths so other test modules aren't affected
|
||||
for _p in _src_paths:
|
||||
if _p not in sys.path:
|
||||
sys.path.append(_p)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def driver():
|
||||
"""Headless Chrome WebDriver, shared across tests in this module."""
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"""Tests for websocket/handler.py — WebSocket manager."""
|
||||
"""Tests for ws_manager/handler.py — WebSocket manager."""
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from websocket.handler import WebSocketManager, WSEvent
|
||||
from ws_manager.handler import WebSocketManager, WSEvent
|
||||
|
||||
|
||||
def test_ws_event_to_json():
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"""Extended tests for websocket/handler.py — broadcast, disconnect, convenience."""
|
||||
"""Extended tests for ws_manager/handler.py — broadcast, disconnect, convenience."""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
@@ -6,7 +6,7 @@ from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from websocket.handler import WebSocketManager, WSEvent
|
||||
from ws_manager.handler import WebSocketManager, WSEvent
|
||||
|
||||
|
||||
class TestWSEventSerialization:
|
||||
|
||||
Reference in New Issue
Block a user