mirror of
https://github.com/ipnet-mesh/meshcore-hub.git
synced 2026-03-28 17:42:56 +01:00
Merge pull request #3 from ipnet-mesh/claude/fix-linting-errors-01GKk8AffQQFixCbjZ4egqn2
Fix flake8 and mypy linting errors
This commit is contained in:
2
.flake8
2
.flake8
@@ -1,6 +1,6 @@
|
||||
[flake8]
|
||||
max-line-length = 88
|
||||
extend-ignore = E203, E501, W503
|
||||
extend-ignore = B008, E203, E402, E501, W503
|
||||
exclude =
|
||||
.git,
|
||||
__pycache__,
|
||||
|
||||
@@ -21,6 +21,7 @@ repos:
|
||||
rev: 7.0.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
args: ["--config=.flake8"]
|
||||
additional_dependencies:
|
||||
- flake8-bugbear
|
||||
- flake8-comprehensions
|
||||
@@ -29,6 +30,7 @@ repos:
|
||||
rev: v1.9.0
|
||||
hooks:
|
||||
- id: mypy
|
||||
exclude: ^alembic/
|
||||
additional_dependencies:
|
||||
- pydantic>=2.0.0
|
||||
- pydantic-settings>=2.0.0
|
||||
|
||||
@@ -106,9 +106,25 @@ plugins = ["pydantic.mypy"]
|
||||
module = [
|
||||
"paho.*",
|
||||
"uvicorn.*",
|
||||
"alembic.*",
|
||||
]
|
||||
ignore_missing_imports = true
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = [
|
||||
"tests.*",
|
||||
"conftest",
|
||||
]
|
||||
disallow_untyped_defs = false
|
||||
disallow_incomplete_defs = false
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = [
|
||||
"alembic.env",
|
||||
"alembic.versions.*",
|
||||
]
|
||||
ignore_errors = true
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
minversion = "7.0"
|
||||
asyncio_mode = "auto"
|
||||
|
||||
@@ -71,7 +71,7 @@ def db() -> None:
|
||||
def db_upgrade(revision: str, database_url: str | None) -> None:
|
||||
"""Upgrade database to a later version."""
|
||||
import os
|
||||
from alembic import command
|
||||
from alembic import command # type: ignore[attr-defined]
|
||||
from alembic.config import Config
|
||||
|
||||
click.echo(f"Upgrading database to revision: {revision}")
|
||||
@@ -101,7 +101,7 @@ def db_upgrade(revision: str, database_url: str | None) -> None:
|
||||
def db_downgrade(revision: str, database_url: str | None) -> None:
|
||||
"""Revert database to a previous version."""
|
||||
import os
|
||||
from alembic import command
|
||||
from alembic import command # type: ignore[attr-defined]
|
||||
from alembic.config import Config
|
||||
|
||||
click.echo(f"Downgrading database to revision: {revision}")
|
||||
@@ -130,7 +130,7 @@ def db_downgrade(revision: str, database_url: str | None) -> None:
|
||||
)
|
||||
def db_revision(message: str, autogenerate: bool) -> None:
|
||||
"""Create a new database migration."""
|
||||
from alembic import command
|
||||
from alembic import command # type: ignore[attr-defined]
|
||||
from alembic.config import Config
|
||||
|
||||
click.echo(f"Creating new revision: {message}")
|
||||
@@ -151,7 +151,7 @@ def db_revision(message: str, autogenerate: bool) -> None:
|
||||
def db_current(database_url: str | None) -> None:
|
||||
"""Show current database revision."""
|
||||
import os
|
||||
from alembic import command
|
||||
from alembic import command # type: ignore[attr-defined]
|
||||
from alembic.config import Config
|
||||
|
||||
alembic_cfg = Config("alembic.ini")
|
||||
@@ -164,7 +164,7 @@ def db_current(database_url: str | None) -> None:
|
||||
@db.command("history")
|
||||
def db_history() -> None:
|
||||
"""Show database migration history."""
|
||||
from alembic import command
|
||||
from alembic import command # type: ignore[attr-defined]
|
||||
from alembic.config import Config
|
||||
|
||||
alembic_cfg = Config("alembic.ini")
|
||||
|
||||
@@ -6,6 +6,7 @@ from typing import AsyncGenerator
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from sqlalchemy import text
|
||||
|
||||
from meshcore_hub import __version__
|
||||
from meshcore_hub.common.database import DatabaseManager
|
||||
@@ -115,7 +116,7 @@ def create_app(
|
||||
try:
|
||||
db = get_db_manager()
|
||||
with db.session_scope() as session:
|
||||
session.execute("SELECT 1")
|
||||
session.execute(text("SELECT 1"))
|
||||
return {"status": "ready", "database": "connected"}
|
||||
except Exception as e:
|
||||
return {"status": "not_ready", "database": str(e)}
|
||||
|
||||
@@ -62,7 +62,7 @@ def _handle_message(
|
||||
"""
|
||||
text = payload.get("text")
|
||||
if not text:
|
||||
logger.warning(f"Message missing text content")
|
||||
logger.warning("Message missing text content")
|
||||
return
|
||||
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy import BigInteger, DateTime, ForeignKey, Index, Integer, String
|
||||
from sqlalchemy import BigInteger, DateTime, ForeignKey, Index, Integer
|
||||
from sqlalchemy.dialects.sqlite import JSON
|
||||
from sqlalchemy.orm import Mapped, mapped_column
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ class MQTTClient:
|
||||
self.config = config
|
||||
self.topic_builder = TopicBuilder(config.prefix)
|
||||
self._client = mqtt.Client(
|
||||
callback_api_version=CallbackAPIVersion.VERSION2,
|
||||
callback_api_version=CallbackAPIVersion.VERSION2, # type: ignore[call-arg]
|
||||
client_id=config.client_id,
|
||||
clean_session=config.clean_session,
|
||||
)
|
||||
@@ -211,7 +211,7 @@ class MQTTClient:
|
||||
pattern_parts = pattern.split("/")
|
||||
topic_parts = topic.split("/")
|
||||
|
||||
for i, (p, t) in enumerate(zip(pattern_parts, topic_parts)):
|
||||
for _i, (p, t) in enumerate(zip(pattern_parts, topic_parts)):
|
||||
if p == "#":
|
||||
return True
|
||||
if p != "+" and p != t:
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import click
|
||||
|
||||
from meshcore_hub.common.config import InterfaceMode
|
||||
from meshcore_hub.common.logging import configure_logging
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import time
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
@@ -261,9 +260,9 @@ class MeshCoreDevice(BaseMeshCoreDevice):
|
||||
"""
|
||||
super().__init__(config)
|
||||
self._running = False
|
||||
self._mc = None
|
||||
self._loop = None
|
||||
self._subscriptions = []
|
||||
self._mc: Any = None
|
||||
self._loop: Any = None
|
||||
self._subscriptions: list[Any] = []
|
||||
|
||||
def connect(self) -> bool:
|
||||
"""Connect to the MeshCore device."""
|
||||
@@ -309,7 +308,7 @@ class MeshCoreDevice(BaseMeshCoreDevice):
|
||||
if self_info:
|
||||
self._public_key = self_info.get("public_key")
|
||||
if self._public_key:
|
||||
logger.info(f"Retrieved device public key from self_info")
|
||||
logger.info("Retrieved device public key from self_info")
|
||||
else:
|
||||
logger.warning(
|
||||
"Device self_info missing public_key field. "
|
||||
@@ -352,7 +351,7 @@ class MeshCoreDevice(BaseMeshCoreDevice):
|
||||
|
||||
for mc_event_type, our_event_type in event_map.items():
|
||||
|
||||
async def callback(event, et=our_event_type):
|
||||
async def callback(event: Any, et: EventType = our_event_type) -> None:
|
||||
# Convert event to dict and dispatch
|
||||
# Use event.payload for the full data (text, etc.)
|
||||
# event.attributes only contains filtering fields
|
||||
@@ -399,7 +398,7 @@ class MeshCoreDevice(BaseMeshCoreDevice):
|
||||
|
||||
try:
|
||||
|
||||
async def _send():
|
||||
async def _send() -> None:
|
||||
await self._mc.commands.send_msg(destination, text)
|
||||
|
||||
self._loop.run_until_complete(_send())
|
||||
@@ -422,7 +421,7 @@ class MeshCoreDevice(BaseMeshCoreDevice):
|
||||
|
||||
try:
|
||||
|
||||
async def _send():
|
||||
async def _send() -> None:
|
||||
await self._mc.commands.send_chan_msg(channel_idx, text)
|
||||
|
||||
self._loop.run_until_complete(_send())
|
||||
@@ -440,7 +439,7 @@ class MeshCoreDevice(BaseMeshCoreDevice):
|
||||
|
||||
try:
|
||||
|
||||
async def _send():
|
||||
async def _send() -> None:
|
||||
await self._mc.commands.send_advert(flood=flood)
|
||||
|
||||
self._loop.run_until_complete(_send())
|
||||
@@ -458,7 +457,7 @@ class MeshCoreDevice(BaseMeshCoreDevice):
|
||||
|
||||
try:
|
||||
|
||||
async def _request():
|
||||
async def _request() -> None:
|
||||
await self._mc.commands.send_statusreq(target)
|
||||
|
||||
self._loop.run_until_complete(_request())
|
||||
@@ -476,7 +475,7 @@ class MeshCoreDevice(BaseMeshCoreDevice):
|
||||
|
||||
try:
|
||||
|
||||
async def _request():
|
||||
async def _request() -> None:
|
||||
await self._mc.commands.send_telemetry_req(target)
|
||||
|
||||
self._loop.run_until_complete(_request())
|
||||
@@ -494,7 +493,7 @@ class MeshCoreDevice(BaseMeshCoreDevice):
|
||||
|
||||
try:
|
||||
|
||||
async def _set_time():
|
||||
async def _set_time() -> None:
|
||||
await self._mc.commands.set_time(timestamp)
|
||||
|
||||
self._loop.run_until_complete(_set_time())
|
||||
@@ -512,7 +511,7 @@ class MeshCoreDevice(BaseMeshCoreDevice):
|
||||
|
||||
try:
|
||||
|
||||
async def _start_fetching():
|
||||
async def _start_fetching() -> None:
|
||||
await self._mc.start_auto_message_fetching()
|
||||
|
||||
self._loop.run_until_complete(_start_fetching())
|
||||
@@ -531,7 +530,7 @@ class MeshCoreDevice(BaseMeshCoreDevice):
|
||||
self._setup_event_subscriptions()
|
||||
|
||||
# Run the async event loop
|
||||
async def _run_loop():
|
||||
async def _run_loop() -> None:
|
||||
while self._running and self._connected:
|
||||
await asyncio.sleep(0.1)
|
||||
|
||||
|
||||
@@ -158,7 +158,6 @@ class MockMeshCoreDevice(BaseMeshCoreDevice):
|
||||
logger.warning("Simulated send failure")
|
||||
return False
|
||||
|
||||
ts = timestamp or int(time.time())
|
||||
logger.info(f"Mock: Sending message to {destination[:12]}...: {text[:20]}...")
|
||||
|
||||
# Simulate send confirmation after delay
|
||||
@@ -199,7 +198,6 @@ class MockMeshCoreDevice(BaseMeshCoreDevice):
|
||||
logger.warning("Simulated send failure")
|
||||
return False
|
||||
|
||||
ts = timestamp or int(time.time())
|
||||
logger.info(f"Mock: Sending message to channel {channel_idx}: {text[:20]}...")
|
||||
|
||||
return True
|
||||
|
||||
@@ -15,7 +15,6 @@ from typing import Any, Optional
|
||||
from meshcore_hub.common.mqtt import MQTTClient, MQTTConfig
|
||||
from meshcore_hub.interface.device import (
|
||||
BaseMeshCoreDevice,
|
||||
DeviceConfig,
|
||||
EventType,
|
||||
create_device,
|
||||
)
|
||||
|
||||
@@ -6,7 +6,6 @@ In SENDER mode, the interface:
|
||||
3. Executes received commands on the device
|
||||
"""
|
||||
|
||||
import json
|
||||
import logging
|
||||
import signal
|
||||
import threading
|
||||
@@ -16,7 +15,6 @@ from typing import Any, Optional
|
||||
from meshcore_hub.common.mqtt import MQTTClient, MQTTConfig
|
||||
from meshcore_hub.interface.device import (
|
||||
BaseMeshCoreDevice,
|
||||
DeviceConfig,
|
||||
create_device,
|
||||
)
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ from typing import AsyncGenerator
|
||||
|
||||
import httpx
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.staticfiles import StaticFiles
|
||||
from fastapi.templating import Jinja2Templates
|
||||
|
||||
@@ -132,7 +131,8 @@ def create_app(
|
||||
|
||||
def get_templates(request: Request) -> Jinja2Templates:
|
||||
"""Get templates from app state."""
|
||||
return request.app.state.templates
|
||||
templates: Jinja2Templates = request.app.state.templates
|
||||
return templates
|
||||
|
||||
|
||||
def get_network_context(request: Request) -> dict:
|
||||
|
||||
@@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
def load_members(members_file: str | None) -> list[dict]:
|
||||
def load_members(members_file: str | None) -> list[dict[str, str]]:
|
||||
"""Load members from JSON file.
|
||||
|
||||
Args:
|
||||
@@ -32,9 +32,11 @@ def load_members(members_file: str | None) -> list[dict]:
|
||||
data = json.load(f)
|
||||
# Handle both list and dict with "members" key
|
||||
if isinstance(data, list):
|
||||
return data
|
||||
return list(data)
|
||||
elif isinstance(data, dict) and "members" in data:
|
||||
return data["members"]
|
||||
members = data["members"]
|
||||
if isinstance(members, list):
|
||||
return list(members)
|
||||
else:
|
||||
logger.warning(f"Members file not found: {members_file}")
|
||||
except Exception as e:
|
||||
|
||||
@@ -29,7 +29,7 @@ async def messages_list(
|
||||
offset = (page - 1) * limit
|
||||
|
||||
# Build query params
|
||||
params = {"limit": limit, "offset": offset}
|
||||
params: dict[str, int | str] = {"limit": limit, "offset": offset}
|
||||
if message_type:
|
||||
params["message_type"] = message_type
|
||||
if channel_idx is not None:
|
||||
|
||||
@@ -28,7 +28,7 @@ async def nodes_list(
|
||||
offset = (page - 1) * limit
|
||||
|
||||
# Build query params
|
||||
params = {"limit": limit, "offset": offset}
|
||||
params: dict[str, int | str] = {"limit": limit, "offset": offset}
|
||||
if search:
|
||||
params["search"] = search
|
||||
if adv_type:
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Tests for advertisement API routes."""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestListAdvertisements:
|
||||
"""Tests for GET /advertisements endpoint."""
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Tests for API authentication."""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestAuthenticationFlow:
|
||||
"""Tests for authentication behavior."""
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Tests for command API routes."""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestSendMessage:
|
||||
"""Tests for POST /commands/send-message endpoint."""
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Tests for dashboard API routes."""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestDashboardStats:
|
||||
"""Tests for GET /dashboard/stats endpoint."""
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Tests for message API routes."""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestListMessages:
|
||||
"""Tests for GET /messages endpoint."""
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Tests for node API routes."""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestListNodes:
|
||||
"""Tests for GET /nodes endpoint."""
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Tests for telemetry API routes."""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestListTelemetry:
|
||||
"""Tests for GET /telemetry endpoint."""
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Tests for trace path API routes."""
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestListTracePaths:
|
||||
"""Tests for GET /trace-paths endpoint."""
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
"""Fixtures for collector component tests."""
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
from meshcore_hub.common.database import DatabaseManager
|
||||
from meshcore_hub.common.models import Base
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"""Tests for advertisement handler."""
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import select
|
||||
|
||||
from meshcore_hub.common.models import Advertisement, Node
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"""Tests for message handlers."""
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import select
|
||||
|
||||
from meshcore_hub.common.models import Message, Node
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
"""Tests for telemetry handler."""
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import select
|
||||
|
||||
from meshcore_hub.common.models import Node, Telemetry
|
||||
|
||||
@@ -155,6 +155,7 @@ class TestTelemetryModel:
|
||||
db_session.commit()
|
||||
|
||||
assert telemetry.id is not None
|
||||
assert telemetry.parsed_data is not None
|
||||
assert telemetry.parsed_data["temperature"] == 22.5
|
||||
|
||||
|
||||
@@ -175,4 +176,5 @@ class TestEventLogModel:
|
||||
|
||||
assert event.id is not None
|
||||
assert event.event_type == "BATTERY"
|
||||
assert event.payload is not None
|
||||
assert event.payload["battery_percentage"] == 75
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
"""Fixtures for interface component tests."""
|
||||
|
||||
from collections.abc import Generator
|
||||
|
||||
import pytest
|
||||
|
||||
from meshcore_hub.interface.device import DeviceConfig, EventType
|
||||
from meshcore_hub.interface.device import DeviceConfig
|
||||
from meshcore_hub.interface.mock_device import MockDeviceConfig, MockMeshCoreDevice
|
||||
|
||||
|
||||
@@ -27,7 +29,9 @@ def mock_device_config() -> MockDeviceConfig:
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_device(device_config, mock_device_config) -> MockMeshCoreDevice:
|
||||
def mock_device(
|
||||
device_config: DeviceConfig, mock_device_config: MockDeviceConfig
|
||||
) -> Generator[MockMeshCoreDevice, None, None]:
|
||||
"""Create a mock device instance for testing."""
|
||||
device = MockMeshCoreDevice(device_config, mock_device_config)
|
||||
yield device
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
"""Tests for device abstraction."""
|
||||
|
||||
import pytest
|
||||
|
||||
from meshcore_hub.interface.device import (
|
||||
DeviceConfig,
|
||||
EventType,
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"""Tests for mock device implementation."""
|
||||
|
||||
import pytest
|
||||
import time
|
||||
import threading
|
||||
|
||||
from meshcore_hub.interface.device import EventType
|
||||
from meshcore_hub.interface.mock_device import (
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
import pytest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from meshcore_hub.interface.device import DeviceConfig, EventType
|
||||
from meshcore_hub.interface.mock_device import MockDeviceConfig, MockMeshCoreDevice
|
||||
from meshcore_hub.interface.device import EventType
|
||||
from meshcore_hub.interface.receiver import Receiver, create_receiver
|
||||
|
||||
|
||||
@@ -69,7 +68,7 @@ class TestCreateReceiver:
|
||||
|
||||
def test_creates_receiver_with_mock_device(self):
|
||||
"""Test creating receiver with mock device."""
|
||||
with patch("meshcore_hub.interface.receiver.MQTTClient") as MockMQTT:
|
||||
with patch("meshcore_hub.interface.receiver.MQTTClient"):
|
||||
receiver = create_receiver(mock=True)
|
||||
|
||||
assert receiver is not None
|
||||
@@ -78,8 +77,8 @@ class TestCreateReceiver:
|
||||
|
||||
def test_creates_receiver_with_custom_mqtt_config(self):
|
||||
"""Test creating receiver with custom MQTT configuration."""
|
||||
with patch("meshcore_hub.interface.receiver.MQTTClient") as MockMQTT:
|
||||
receiver = create_receiver(
|
||||
with patch("meshcore_hub.interface.receiver.MQTTClient") as mock_mqtt:
|
||||
create_receiver(
|
||||
mock=True,
|
||||
mqtt_host="mqtt.example.com",
|
||||
mqtt_port=8883,
|
||||
@@ -87,8 +86,8 @@ class TestCreateReceiver:
|
||||
)
|
||||
|
||||
# Verify MQTT client was created with correct config
|
||||
MockMQTT.assert_called_once()
|
||||
config = MockMQTT.call_args[0][0]
|
||||
mock_mqtt.assert_called_once()
|
||||
config = mock_mqtt.call_args[0][0]
|
||||
assert config.host == "mqtt.example.com"
|
||||
assert config.port == 8883
|
||||
assert config.prefix == "custom"
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
import pytest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from meshcore_hub.interface.device import DeviceConfig, EventType
|
||||
from meshcore_hub.interface.mock_device import MockDeviceConfig, MockMeshCoreDevice
|
||||
from meshcore_hub.interface.sender import Sender, create_sender
|
||||
|
||||
|
||||
@@ -107,7 +105,7 @@ class TestCreateSender:
|
||||
|
||||
def test_creates_sender_with_mock_device(self):
|
||||
"""Test creating sender with mock device."""
|
||||
with patch("meshcore_hub.interface.sender.MQTTClient") as MockMQTT:
|
||||
with patch("meshcore_hub.interface.sender.MQTTClient"):
|
||||
sender = create_sender(mock=True)
|
||||
|
||||
assert sender is not None
|
||||
@@ -116,16 +114,16 @@ class TestCreateSender:
|
||||
|
||||
def test_creates_sender_with_custom_mqtt_config(self):
|
||||
"""Test creating sender with custom MQTT configuration."""
|
||||
with patch("meshcore_hub.interface.sender.MQTTClient") as MockMQTT:
|
||||
sender = create_sender(
|
||||
with patch("meshcore_hub.interface.sender.MQTTClient") as mock_mqtt:
|
||||
create_sender(
|
||||
mock=True,
|
||||
mqtt_host="mqtt.example.com",
|
||||
mqtt_port=8883,
|
||||
mqtt_prefix="custom",
|
||||
)
|
||||
|
||||
MockMQTT.assert_called_once()
|
||||
config = MockMQTT.call_args[0][0]
|
||||
mock_mqtt.assert_called_once()
|
||||
config = mock_mqtt.call_args[0][0]
|
||||
assert config.host == "mqtt.example.com"
|
||||
assert config.port == 8883
|
||||
assert config.prefix == "custom"
|
||||
|
||||
Reference in New Issue
Block a user